--- /dev/null
+FILES
+INSTALL
+Makefile.in
+README
+TODO
+aclocal.m4
+cgi-bin/printenv
+cgi-src/Makefile.in
+cgi-src/redirect.8
+cgi-src/redirect.c
+cgi-src/phf.c
+cgi-src/ssi.8
+cgi-src/ssi.c
+config.guess
+config.h
+config.sub
+configure
+configure.in
+extras/Makefile.in
+extras/htpasswd.1
+extras/htpasswd.c
+extras/makeweb.1
+extras/makeweb.c
+extras/syslogtocern
+extras/syslogtocern.8
+index.html
+install-sh
+libhttpd.c
+libhttpd.h
+match.c
+match.h
+mime_encodings.txt
+mime_types.txt
+mmc.c
+mmc.h
+strerror.c
+tdate_parse.c
+tdate_parse.h
+thttpd.8
+thttpd.c
+fdwatch.c
+fdwatch.h
+timers.c
+timers.h
+version.h
+scripts/500.thttpd-rotate
+scripts/thttpd.sh
+scripts/thttpd_wrapper
+contrib/redhat-rpm/thttpd.spec
+contrib/redhat-rpm/thttpd.init
+contrib/redhat-rpm/thttpd.conf
--- /dev/null
+To build:
+
+ % ./configure
+
+ Edit config.h to change the configuration options if necessary.
+
+ % make
+
+
+To install:
+
+ % make install
+
+ Edit one of your system rc files to run thttpd at boot time. Do NOT
+ run it from inetd, that setup is inefficient so thttpd doesn't support it.
+
+
+Red Hat:
+
+ On Red Hat Linux systems you can use RPM to install thttpd, like so:
+
+ cd /usr/src/redhat/SOURCES
+ wget http://www.acme.com/software/thttpd/thttpd-2.29.tar.gz
+ rpm -ta thttpd-2.29.tar.gz
+ rpm -i /usr/src/redhat/RPMS/i386/thttpd-2.29-1.i386.rpm
+
+
+Solaris:
+
+ If you're running Solaris and you want to use the security-enhancing
+ chroot feature, then you must create the TCP device files in the chroot
+ tree. There is no way around this, Solaris needs these files to accept
+ network connections. You need /dev/tcp, which is a symbolic link like so:
+ /dev/tcp -> ../devices/pseudo/clone@0:tcp
+ And you also need the file it points to:
+ crw-rw-rw- bin 11, 42 May 24 21:32 /devices/pseudo/clone@0:tcp
+ You probably need some other files too, such as shared libraries and
+ a tmp directory. Check out the man page for ftpd, it has a big long
+ shell script for setting up an anonymous ftp area that should also
+ work for thttpd.
--- /dev/null
+dpkg-buildpackage: info: source package thttpd
+dpkg-buildpackage: info: source version 2.29-1
+dpkg-buildpackage: info: source distribution unstable
+dpkg-buildpackage: info: source changed by Ralph Ronnquist <ralph.ronnquist@gmail.com>
+ dpkg-source --before-build thttpd-2.29
+dpkg-buildpackage: info: host architecture amd64
+ fakeroot debian/rules clean
+dh clean --with autotools_dev --without systemd
+ dh_testdir
+ dh_auto_clean
+ make -j1 distclean
+make[1]: Entering directory '/home/ralph/src/thttpd/thttpd-2.29'
+for i in ; do ( \
+ cd $i ; \
+ pwd ; \
+ make -w distclean \
+) ; done
+rm -f thttpd thttpd.o libhttpd.o fdwatch.o mmc.o timers.o match.o tdate_parse.o mime_encodings.h mime_types.h Makefile config.cache config.log config.status tags
+make[1]: Leaving directory '/home/ralph/src/thttpd/thttpd-2.29'
+ dh_autotools-dev_restoreconfig
+ for c_g in `find . -type f -name config.guess` ; do if test -e "$c_g.dh-orig" ; then mv -f "$c_g.dh-orig" "$c_g" ; fi ; done
+ for c_s in `find . -type f -name config.sub` ; do if test -e "$c_s.dh-orig" ; then mv -f "$c_s.dh-orig" "$c_s" ; fi ; done
+ find . -type f \( -name config.guess.dh-orig -o -name config.sub.dh-orig \) -delete
+ dh_clean
+ rm -f debian/debhelper-build-stamp
+ rm -f debian/thttpd.substvars
+ rm -f debian/thttpd.*.debhelper
+ rm -rf debian/thttpd/
+ rm -rf debian/.debhelper/
+ rm -f debian/*.debhelper.log
+ rm -f debian/files
+ find . \( \( \
+ \( -path .\*/.git -o -path .\*/.svn -o -path .\*/.bzr -o -path .\*/.hg -o -path .\*/CVS \) -prune -o -type f -a \
+ \( -name '#*#' -o -name '.*~' -o -name '*~' -o -name DEADJOE \
+ -o -name '*.orig' -o -name '*.rej' -o -name '*.bak' \
+ -o -name '.*.orig' -o -name .*.rej -o -name '.SUMS' \
+ -o -name TAGS -o \( -path '*/.deps/*' -a -name '*.P' \) \
+ \) -exec rm -f {} + \) -o \
+ \( -type d -a -name autom4te.cache -prune -exec rm -rf {} + \) \)
+ rm -f *-stamp
+ debian/rules build
+dh build --with autotools_dev --without systemd
+ dh_testdir
+ dh_update_autotools_config
+ dh_autotools-dev_updateconfig
+ for c_g in `find -type f -name config.guess` ; do if ! test -e "$c_g.dh-orig" ; then mv -f "$c_g" "$c_g.dh-orig" ; cp -f /usr/share/misc/config.guess "$c_g" ; fi ; done
+ for c_s in `find -type f -name config.sub` ; do if ! test -e "$c_s.dh-orig" ; then mv -f "$c_s" "$c_s.dh-orig" ; cp -f /usr/share/misc/config.sub "$c_s" ; fi ; done
+ debian/rules override_dh_auto_configure
+make[1]: Entering directory '/home/ralph/src/thttpd/thttpd-2.29'
+dh_auto_configure -- --prefix=/usr/local --mandir=/usr/local/man
+ ./configure --build=x86_64-linux-gnu --prefix=/usr --includedir=\${prefix}/include --mandir=\${prefix}/share/man --infodir=\${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir=\${prefix}/lib/x86_64-linux-gnu --libexecdir=\${prefix}/lib/x86_64-linux-gnu --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr/local --mandir=/usr/local/man
+creating cache ./config.cache
+checking host system type... x86_64-pc-linux-gnu
+checking target system type... x86_64-pc-linux-gnu
+checking build system type... x86_64-pc-linux-gnu
+checking for gcc... gcc
+checking whether the C compiler (gcc -g -O2 ) works... yes
+checking whether the C compiler (gcc -g -O2 ) is a cross-compiler... no
+checking whether we are using GNU C... yes
+checking whether gcc accepts -g... yes
+checking gcc version... 6
+checking how to link static binaries... unknown
+checking for __progname... yes
+checking how to run the C preprocessor... gcc -E
+checking for fcntl.h... yes
+checking for grp.h... yes
+checking for memory.h... yes
+checking for paths.h... yes
+checking for poll.h... yes
+checking for sys/poll.h... yes
+checking for sys/devpoll.h... no
+checking for sys/event.h... no
+checking for osreldate.h... no
+checking whether time.h and sys/time.h may both be included... yes
+checking for dirent.h that defines DIR... yes
+checking for opendir in -ldir... no
+checking for /usr/local/v6/lib... no
+checking for gethostbyname... yes
+checking for socket... yes
+checking for main in -linet6... no
+checking for crypt... no
+checking for crypt in -lcrypt... yes
+checking for hstrerror... yes
+checking for strerror... yes
+checking for waitpid... yes
+checking for vsnprintf... yes
+checking for daemon... yes
+checking for setsid... yes
+checking for setlogin... no
+checking for getaddrinfo... yes
+checking for getnameinfo... yes
+checking for gai_strerror... yes
+checking for kqueue... no
+checking for sigset... yes
+checking for atoll... yes
+checking for unistd.h... yes
+checking for getpagesize... yes
+checking for working mmap... yes
+checking for select... yes
+checking for poll... yes
+checking if struct tm has tm_gmtoff member... yes
+checking if int64_t exists... yes
+checking if socklen_t exists... yes
+checking whether make sets ${MAKE}... yes
+checking for a BSD compatible install... /usr/bin/install -c
+updating cache ./config.cache
+creating ./config.status
+creating Makefile
+creating cgi-src/Makefile
+creating extras/Makefile
+make[1]: Leaving directory '/home/ralph/src/thttpd/thttpd-2.29'
+ dh_auto_build
+ make -j1
+make[1]: Entering directory '/home/ralph/src/thttpd/thttpd-2.29'
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -c thttpd.c
+thttpd.c: In function ‘main’:
+thttpd.c:611:12: warning: implicit declaration of function ‘sigset’ [-Wimplicit-function-declaration]
+ (void) sigset( SIGTERM, handle_term );
+ ^~~~~~
+rm -f mime_encodings.h
+sed < mime_encodings.txt > mime_encodings.h \
+ -e 's/#.*//' -e 's/[ ]*$//' -e '/^$/d' \
+ -e 's/[ ][ ]*/", 0, "/' -e 's/^/{ "/' -e 's/$/", 0 },/'
+rm -f mime_types.h
+sed < mime_types.txt > mime_types.h \
+ -e 's/#.*//' -e 's/[ ]*$//' -e '/^$/d' \
+ -e 's/[ ][ ]*/", 0, "/' -e 's/^/{ "/' -e 's/$/", 0 },/'
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -c libhttpd.c
+In file included from /usr/include/string.h:630:0,
+ from /usr/include/memory.h:29,
+ from libhttpd.c:47:
+libhttpd.c: In function ‘auth_check2’:
+libhttpd.c:1086:15: warning: implicit declaration of function ‘crypt’ [-Wimplicit-function-declaration]
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ ^
+libhttpd.c:1086:15: warning: passing argument 1 of ‘__builtin_strlen’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ ^
+libhttpd.c:1086:15: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1086:15: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ ^
+libhttpd.c:1086:15: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1086:15: warning: passing argument 1 of ‘__builtin_strlen’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ ^
+libhttpd.c:1086:15: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1086:15: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ ^
+libhttpd.c:1086:15: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1086:15: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ ^
+libhttpd.c:1086:15: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1086:15: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ ^
+libhttpd.c:1086:15: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1135:19: warning: passing argument 1 of ‘__builtin_strlen’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, cryp ), cryp ) == 0 )
+ ^
+libhttpd.c:1135:19: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1135:19: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, cryp ), cryp ) == 0 )
+ ^
+libhttpd.c:1135:19: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1135:19: warning: passing argument 1 of ‘__builtin_strlen’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, cryp ), cryp ) == 0 )
+ ^
+libhttpd.c:1135:19: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1135:19: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, cryp ), cryp ) == 0 )
+ ^
+libhttpd.c:1135:19: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1135:19: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, cryp ), cryp ) == 0 )
+ ^
+libhttpd.c:1135:19: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c:1135:19: warning: passing argument 1 of ‘__builtin_strcmp’ makes pointer from integer without a cast [-Wint-conversion]
+ if ( strcmp( crypt( authpass, cryp ), cryp ) == 0 )
+ ^
+libhttpd.c:1135:19: note: expected ‘const char *’ but argument is of type ‘int’
+libhttpd.c: In function ‘cgi_child’:
+libhttpd.c:3557:12: warning: implicit declaration of function ‘sigset’ [-Wimplicit-function-declaration]
+ (void) sigset( SIGPIPE, SIG_DFL );
+ ^~~~~~
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -c fdwatch.c
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -c mmc.c
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -c timers.c
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -c match.c
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -c tdate_parse.c
+gcc -O2 -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 -I. -o thttpd thttpd.o libhttpd.o fdwatch.o mmc.o timers.o match.o tdate_parse.o -lcrypt
+for i in ; do ( \
+ cd $i ; \
+ pwd ; \
+ make -w \
+ WEBDIR=/usr/local/www \
+ CGIBINDIR=/usr/local/www/cgi-bin \
+ MANDIR=/usr/local/man \
+ WEBGROUP=www \
+) ; done
+make[1]: Leaving directory '/home/ralph/src/thttpd/thttpd-2.29'
+ dh_auto_test
+ create-stamp debian/debhelper-build-stamp
+ fakeroot debian/rules binary
+dh binary --with autotools_dev --without systemd
+ create-stamp debian/debhelper-build-stamp
+ dh_testroot
+ dh_prep
+ rm -f debian/thttpd.substvars
+ rm -f debian/thttpd.*.debhelper
+ rm -rf debian/thttpd/
+ dh_auto_install
+ install -d debian/thttpd
+ make -j1 install DESTDIR=/home/ralph/src/thttpd/thttpd-2.29/debian/thttpd AM_UPDATE_INFO_DIR=no
+make[1]: Entering directory '/home/ralph/src/thttpd/thttpd-2.29'
+mkdir -p /home/ralph/src/thttpd/thttpd-2.29/debian/thttpd/usr/local/sbin
+/usr/bin/install -c -m 555 -o bin -g bin thttpd /home/ralph/src/thttpd/thttpd-2.29/debian/thttpd/usr/local/sbin
+mkdir -p /home/ralph/src/thttpd/thttpd-2.29/debian/thttpd/usr/local/man/man8
+/usr/bin/install -c -m 444 -o bin -g bin thttpd.8 /home/ralph/src/thttpd/thttpd-2.29/debian/thttpd/usr/local/man/man8
+make[1]: Leaving directory '/home/ralph/src/thttpd/thttpd-2.29'
+ dh_installdocs
+ install -d debian/thttpd/usr/share/doc/thttpd
+ install -p -m0644 debian/README.Debian debian/thttpd/usr/share/doc/thttpd/README.Debian
+ install -p -m0644 debian/copyright debian/thttpd/usr/share/doc/thttpd/copyright
+ dh_installchangelogs
+ install -p -m0644 debian/changelog debian/thttpd/usr/share/doc/thttpd/changelog.Debian
+ dh_perl
+ dh_link
+ dh_strip_nondeterminism
+ dh_compress
+ cd debian/thttpd
+ chmod a-x usr/share/doc/thttpd/changelog.Debian
+ gzip -9nf usr/share/doc/thttpd/changelog.Debian
+ cd '/home/ralph/src/thttpd/thttpd-2.29'
+ dh_fixperms
+ find debian/thttpd -print0 2>/dev/null | xargs -0r chown --no-dereference 0:0
+ find debian/thttpd ! -type l -print0 2>/dev/null | xargs -0r chmod go=rX,u+rw,a-s
+ find debian/thttpd/usr/share/doc -type f ! -regex 'debian/thttpd/usr/share/doc/[^/]*/examples/.*' -print0 2>/dev/null | xargs -0r chmod 0644
+ find debian/thttpd/usr/share/doc -type d -print0 2>/dev/null | xargs -0r chmod 0755
+ find debian/thttpd/usr/share/man -type f -print0 2>/dev/null | xargs -0r chmod 0644
+ find debian/thttpd/usr/include -type f -print0 2>/dev/null | xargs -0r chmod 0644
+ find debian/thttpd/usr/share/applications -type f -print0 2>/dev/null | xargs -0r chmod 0644
+ find debian/thttpd/usr/lib/x86_64-linux-gnu/perl5/5.24 debian/thttpd/usr/share/perl5 -type f -perm -5 -name '*.pm' -print0 2>/dev/null | xargs -0r chmod a-X
+ find debian/thttpd -perm -5 -type f \( -name '*.so.*' -o -name '*.so' -o -name '*.la' -o -name '*.a' -o -name '*.js' -o -name '*.css' -o -name '*.jpeg' -o -name '*.jpg' -o -name '*.png' -o -name '*.gif' -o -name '*.cmxs' \) -print0 2>/dev/null | xargs -0r chmod 0644
+ find debian/thttpd/usr/lib -type f -name '*.ali' -print0 2>/dev/null | xargs -0r chmod uga-w
+ dh_strip
+ install -d debian/.debhelper/thttpd/dbgsym-root/usr/lib/debug/.build-id/16
+ objcopy --only-keep-debug --compress-debug-sections debian/thttpd/usr/local/sbin/thttpd debian/.debhelper/thttpd/dbgsym-root/usr/lib/debug/.build-id/16/c41619dbe2621d5592bc2134a67ffe4f585557.debug
+ chmod 0644 -- debian/.debhelper/thttpd/dbgsym-root/usr/lib/debug/.build-id/16/c41619dbe2621d5592bc2134a67ffe4f585557.debug
+ chown 0:0 -- debian/.debhelper/thttpd/dbgsym-root/usr/lib/debug/.build-id/16/c41619dbe2621d5592bc2134a67ffe4f585557.debug
+ strip --remove-section=.comment --remove-section=.note debian/thttpd/usr/local/sbin/thttpd
+ objcopy --add-gnu-debuglink debian/.debhelper/thttpd/dbgsym-root/usr/lib/debug/.build-id/16/c41619dbe2621d5592bc2134a67ffe4f585557.debug debian/thttpd/usr/local/sbin/thttpd
+ install -d debian/.debhelper/thttpd/dbgsym-root/usr/share/doc
+ ln -s thttpd debian/.debhelper/thttpd/dbgsym-root/usr/share/doc/thttpd-dbgsym
+ dh_makeshlibs
+ rm -f debian/thttpd/DEBIAN/shlibs
+ dh_shlibdeps
+ install -d debian/thttpd/DEBIAN
+ dpkg-shlibdeps -Tdebian/thttpd.substvars debian/thttpd/usr/local/sbin/thttpd
+ dh_installdeb
+ dh_gencontrol
+ echo misc:Depends= >> debian/thttpd.substvars
+ echo misc:Pre-Depends= >> debian/thttpd.substvars
+ install -d debian/.debhelper/thttpd/dbgsym-root/DEBIAN
+ dpkg-gencontrol -pthttpd -ldebian/changelog -Tdebian/thttpd.substvars -Pdebian/.debhelper/thttpd/dbgsym-root -UPre-Depends -URecommends -USuggests -UEnhances -UProvides -UEssential -UConflicts -DPriority=extra -DAuto-Built-Package=debug-symbols -DPackage=thttpd-dbgsym "-DDepends=thttpd (= \${binary:Version})" "-DDescription=Debug symbols for thttpd" -DBuild-Ids=16c41619dbe2621d5592bc2134a67ffe4f585557 -DSection=debug -UMulti-Arch -UReplaces -UBreaks
+ chmod 0644 -- debian/.debhelper/thttpd/dbgsym-root/DEBIAN/control
+ chown 0:0 -- debian/.debhelper/thttpd/dbgsym-root/DEBIAN/control
+ dpkg-gencontrol -pthttpd -ldebian/changelog -Tdebian/thttpd.substvars -Pdebian/thttpd
+ chmod 0644 -- debian/thttpd/DEBIAN/control
+ chown 0:0 -- debian/thttpd/DEBIAN/control
+ dh_md5sums
+ (cd debian/thttpd >/dev/null ; find . -type f ! -regex './DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum | perl -pe 'if (s@^\\@@) { s/\\\\/\\/g; }' > DEBIAN/md5sums) >/dev/null
+ chmod 0644 -- debian/thttpd/DEBIAN/md5sums
+ chown 0:0 -- debian/thttpd/DEBIAN/md5sums
+ (cd debian/.debhelper/thttpd/dbgsym-root >/dev/null ; find . -type f ! -regex './DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum | perl -pe 'if (s@^\\@@) { s/\\\\/\\/g; }' > DEBIAN/md5sums) >/dev/null
+ chmod 0644 -- debian/.debhelper/thttpd/dbgsym-root/DEBIAN/md5sums
+ chown 0:0 -- debian/.debhelper/thttpd/dbgsym-root/DEBIAN/md5sums
+ dh_builddeb
+ dpkg-deb -z1 -Zxz -Sextreme --build debian/.debhelper/thttpd/dbgsym-root ..
+dpkg-deb: building package 'thttpd-dbgsym' in '../thttpd-dbgsym_2.29-1_amd64.deb'.
+ dpkg-deb --build debian/thttpd ..
+dpkg-deb: building package 'thttpd' in '../thttpd_2.29-1_amd64.deb'.
+ dpkg-genbuildinfo --build=binary
+ dpkg-genchanges --build=binary >../thttpd_2.29-1_amd64.changes
+dpkg-genchanges: info: binary-only upload (no source code included)
+ dpkg-source --after-build thttpd-2.29
+dpkg-buildpackage: info: binary-only upload (no source included)
--- /dev/null
+# Generated automatically from Makefile.in by configure.
+# Makefile.in for thttpd
+#
+# Copyright © 1995,1998 by Jef Poskanzer <jef@mail.acme.com>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+
+# Top level hierarchy.
+prefix = /usr/local
+exec_prefix = ${prefix}
+# Pathname of directory to install the binary.
+BINDIR = ${exec_prefix}/sbin
+# Pathname of directory to install the man page.
+MANDIR = /usr/local/man
+# Pathname of directory to install the CGI programs.
+WEBDIR = $(prefix)/www
+
+# CONFIGURE: The group that the web directory belongs to. This is so that
+# the makeweb program can be installed set-group-id to that group, and make
+# subdirectories. If you're not going to use makeweb, ignore this.
+WEBGROUP = www
+
+# CONFIGURE: Directory for CGI executables.
+CGIBINDIR = $(WEBDIR)/cgi-bin
+
+# You shouldn't need to edit anything below here.
+
+CC = gcc
+CCOPT = -O2
+DEFS = -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1
+INCLS = -I.
+CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
+LDFLAGS =
+LIBS = -lcrypt
+NETLIBS =
+INSTALL = /usr/bin/install -c
+
+
+
+.c.o:
+ @rm -f $@
+ $(CC) $(CFLAGS) -c $*.c
+
+SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c
+
+OBJ = $(SRC:.c=.o)
+
+ALL = thttpd
+
+GENHDR = mime_encodings.h mime_types.h
+
+CLEANFILES = $(ALL) $(OBJ) $(GENSRC) $(GENHDR)
+
+#SUBDIRS = cgi-src extras
+
+all: this subdirs
+this: $(ALL)
+
+thttpd: $(OBJ)
+ @rm -f $@
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(NETLIBS)
+
+mime_encodings.h: mime_encodings.txt
+ rm -f mime_encodings.h
+ sed < mime_encodings.txt > mime_encodings.h \
+ -e 's/#.*//' -e 's/[ ]*$$//' -e '/^$$/d' \
+ -e 's/[ ][ ]*/", 0, "/' -e 's/^/{ "/' -e 's/$$/", 0 },/'
+
+mime_types.h: mime_types.txt
+ rm -f mime_types.h
+ sed < mime_types.txt > mime_types.h \
+ -e 's/#.*//' -e 's/[ ]*$$//' -e '/^$$/d' \
+ -e 's/[ ][ ]*/", 0, "/' -e 's/^/{ "/' -e 's/$$/", 0 },/'
+
+
+subdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) \
+ WEBDIR=$(WEBDIR) \
+ CGIBINDIR=$(CGIBINDIR) \
+ MANDIR=$(MANDIR) \
+ WEBGROUP=$(WEBGROUP) \
+ ) ; done
+
+
+install: installthis install-man # installsubdirs
+
+installthis:
+ -mkdir -p $(DESTDIR)$(BINDIR)
+ $(INSTALL) -m 555 -o bin -g bin thttpd $(DESTDIR)$(BINDIR)
+
+install-man:
+ -mkdir -p $(DESTDIR)$(MANDIR)/man8
+ $(INSTALL) -m 444 -o bin -g bin thttpd.8 $(DESTDIR)$(MANDIR)/man8
+
+installsubdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) \
+ WEBDIR=$(WEBDIR) \
+ CGIBINDIR=$(CGIBINDIR) \
+ MANDIR=$(MANDIR) \
+ WEBGROUP=$(WEBGROUP) \
+ install \
+ ) ; done
+
+
+clean: cleansubdirs
+ rm -f $(CLEANFILES)
+
+distclean: distcleansubdirs
+ rm -f $(CLEANFILES) Makefile config.cache config.log config.status tags
+
+cleansubdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) clean \
+ ) ; done
+
+distcleansubdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) distclean \
+ ) ; done
+
+tags:
+ ctags -wtd *.c *.h
+
+tar:
+ @name=`sed -n -e '/SERVER_SOFTWARE/!d' -e 's,.*thttpd/,thttpd-,' -e 's, .*,,p' version.h` ; \
+ rm -rf $$name ; \
+ mkdir $$name ; \
+ tar cf - `cat FILES` | ( cd $$name ; tar xfBp - ) ; \
+ chmod 644 $$name/Makefile.in $$name/config.h $$name/mime_encodings.txt $$name/mime_types.txt ; \
+ chmod 755 $$name/cgi-bin $$name/cgi-src $$name/contrib $$name/contrib/redhat-rpm $$name/extras $$name/scripts ; \
+ tar cf $$name.tar $$name ; \
+ rm -rf $$name ; \
+ gzip $$name.tar
+
+thttpd.o: config.h version.h libhttpd.h fdwatch.h mmc.h timers.h match.h
+libhttpd.o: config.h version.h libhttpd.h mime_encodings.h mime_types.h \
+ mmc.h timers.h match.h tdate_parse.h
+fdwatch.o: fdwatch.h
+mmc.o: mmc.h libhttpd.h
+timers.o: timers.h
+match.o: match.h
+tdate_parse.o: tdate_parse.h
--- /dev/null
+# Makefile.in for thttpd
+#
+# Copyright © 1995,1998 by Jef Poskanzer <jef@mail.acme.com>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+
+# Top level hierarchy.
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+# Pathname of directory to install the binary.
+BINDIR = @sbindir@
+# Pathname of directory to install the man page.
+MANDIR = @mandir@
+# Pathname of directory to install the CGI programs.
+WEBDIR = $(prefix)/www
+
+# CONFIGURE: The group that the web directory belongs to. This is so that
+# the makeweb program can be installed set-group-id to that group, and make
+# subdirectories. If you're not going to use makeweb, ignore this.
+WEBGROUP = www
+
+# CONFIGURE: Directory for CGI executables.
+CGIBINDIR = $(WEBDIR)/cgi-bin
+
+# You shouldn't need to edit anything below here.
+
+CC = @CC@
+CCOPT = @V_CCOPT@
+DEFS = @DEFS@
+INCLS = -I.
+CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+NETLIBS = @V_NETLIBS@
+INSTALL = @INSTALL@
+
+@SET_MAKE@
+
+.c.o:
+ @rm -f $@
+ $(CC) $(CFLAGS) -c $*.c
+
+SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c
+
+OBJ = $(SRC:.c=.o) @LIBOBJS@
+
+ALL = thttpd
+
+GENHDR = mime_encodings.h mime_types.h
+
+CLEANFILES = $(ALL) $(OBJ) $(GENSRC) $(GENHDR)
+
+#SUBDIRS = cgi-src extras
+
+all: this subdirs
+this: $(ALL)
+
+thttpd: $(OBJ)
+ @rm -f $@
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(NETLIBS)
+
+mime_encodings.h: mime_encodings.txt
+ rm -f mime_encodings.h
+ sed < mime_encodings.txt > mime_encodings.h \
+ -e 's/#.*//' -e 's/[ ]*$$//' -e '/^$$/d' \
+ -e 's/[ ][ ]*/", 0, "/' -e 's/^/{ "/' -e 's/$$/", 0 },/'
+
+mime_types.h: mime_types.txt
+ rm -f mime_types.h
+ sed < mime_types.txt > mime_types.h \
+ -e 's/#.*//' -e 's/[ ]*$$//' -e '/^$$/d' \
+ -e 's/[ ][ ]*/", 0, "/' -e 's/^/{ "/' -e 's/$$/", 0 },/'
+
+
+subdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) \
+ WEBDIR=$(WEBDIR) \
+ CGIBINDIR=$(CGIBINDIR) \
+ MANDIR=$(MANDIR) \
+ WEBGROUP=$(WEBGROUP) \
+ ) ; done
+
+
+install: installthis install-man # installsubdirs
+
+installthis:
+ -mkdir -p $(DESTDIR)$(BINDIR)
+ $(INSTALL) -m 555 -o bin -g bin thttpd $(DESTDIR)$(BINDIR)
+
+install-man:
+ -mkdir -p $(DESTDIR)$(MANDIR)/man8
+ $(INSTALL) -m 444 -o bin -g bin thttpd.8 $(DESTDIR)$(MANDIR)/man8
+
+installsubdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) \
+ WEBDIR=$(WEBDIR) \
+ CGIBINDIR=$(CGIBINDIR) \
+ MANDIR=$(MANDIR) \
+ WEBGROUP=$(WEBGROUP) \
+ install \
+ ) ; done
+
+
+clean: cleansubdirs
+ rm -f $(CLEANFILES)
+
+distclean: distcleansubdirs
+ rm -f $(CLEANFILES) Makefile config.cache config.log config.status tags
+
+cleansubdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) clean \
+ ) ; done
+
+distcleansubdirs:
+ for i in $(SUBDIRS) ; do ( \
+ cd $$i ; \
+ pwd ; \
+ $(MAKE) $(MFLAGS) distclean \
+ ) ; done
+
+tags:
+ ctags -wtd *.c *.h
+
+tar:
+ @name=`sed -n -e '/SERVER_SOFTWARE/!d' -e 's,.*thttpd/,thttpd-,' -e 's, .*,,p' version.h` ; \
+ rm -rf $$name ; \
+ mkdir $$name ; \
+ tar cf - `cat FILES` | ( cd $$name ; tar xfBp - ) ; \
+ chmod 644 $$name/Makefile.in $$name/config.h $$name/mime_encodings.txt $$name/mime_types.txt ; \
+ chmod 755 $$name/cgi-bin $$name/cgi-src $$name/contrib $$name/contrib/redhat-rpm $$name/extras $$name/scripts ; \
+ tar cf $$name.tar $$name ; \
+ rm -rf $$name ; \
+ gzip $$name.tar
+
+thttpd.o: config.h version.h libhttpd.h fdwatch.h mmc.h timers.h match.h
+libhttpd.o: config.h version.h libhttpd.h mime_encodings.h mime_types.h \
+ mmc.h timers.h match.h tdate_parse.h
+fdwatch.o: fdwatch.h
+mmc.o: mmc.h libhttpd.h
+timers.o: timers.h
+match.o: match.h
+tdate_parse.o: tdate_parse.h
--- /dev/null
+ thttpd - tiny/turbo/throttling HTTP server
+ version 2.29 of 23May2018
+
+thttpd is a simple, small, portable, fast, and secure HTTP server.
+
+Simple: It handles only the minimum necessary to implement HTTP/1.1.
+
+Small: See the size comparison chart at
+http://www.acme.com/software/thttpd/notes.html#sizes. It also has a
+very small run-time size, since it does not fork and is very careful about
+memory allocation.
+
+Portable: It compiles cleanly on FreeBSD 2.x/3.x, SunOS 4.1.x, Solaris 2.x,
+BSD/OS 2.x, Linux 1.2.x, OSF/1 (on a 64-bit Alpha), and no doubt many others.
+
+Fast: In typical use it's about as fast as the best full-featured servers
+(Apache, NCSA, Netscape). Under extreme load it's much faster.
+
+Secure: It goes to great lengths to protect the web server machine
+against attacks and breakins from other sites.
+
+It also has one extremely useful feature (URL-traffic-based throttling) that
+no other server currently has.
+
+See the manual entry for more details. See the INSTALL file for
+configuration and installation instructions. Check the web page
+(http://www.acme.com/software/thttpd/) for updates, or add yourself to
+the mailing list by sending a "subscribe" to thttpd-announce-request@mail.acme.com.
+
+Comments to:
+ Jef Poskanzer jef@mail.acme.com http://www.acme.com/jef/
--- /dev/null
+- - - - - - - - - - high priority - - - - - - - - - -
+
+IPv6 not working right.
+
+Problem with ACME News downloads. PATH_INFO interferes with the authorization.
+
+Why is the client's IP address showing up in paths?
+
+Fetches with numeric IP addresses and no Host: header are screwing up the
+vhost code?
+143.90.193.229 - - [06/Apr/2000:09:21:34 -0700] "GET /209.133.38.22/software/thttpd/ HTTP/1.0" 200 12093 "http://www.dbphotography.demon.co.uk/index.html" "Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)"
+143.90.193.229 - - [06/Apr/2000:09:21:37 -0700] "GET /143.90.193.229/software/thttpd/anvil_thttpd.gif HTTP/1.0" 403 - "http://www.acme.com/software/thttpd/" "Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)"
+
+Have directory indexing skip files that start with dot? Except ..?
+In libhttpd.c:
++ if (*(de->d_name) == '.' && *(de->d_name+1) != '.')
++ continue;
+ namlen = NAMLEN(de);
+
+Add comment on INDEX_NAMES that it should be simple filenames only.
+
+The error page generated for non-local referers should include the
+original URL as an active link.
+
+Make open in mmc.c use O_NONBLOCK flag, to prevent DOS attack via
+a named pipe?
+
+- - - - - - - - - - later - - - - - - - - - -
+
+Document how symlinks interact with .htpasswd - authorization is checked
+on the result of the symlink, and not the origin.
+
+SIGHUP log re-opening doesn't work if you started as root.
+
+Change redirect to put the Refresh command in the HTTP headers, instead of
+a META tag.
+
+Add TCP_NODELAY, but after CGIs get spawned.
+
+Add stat cache? 1 minute expiry?
+
+Ifdef the un-close-on-exec CGI thing for Linux only.
+
+Add keep-alives, via a new state in thttpd.c.
+
+- - - - - - - - - - someday - - - - - - - - - -
+
+The special world-permissions checking is probably bogus. For one
+thing, it doesn't handle restrictive permissions on parent directories
+properly. It should probably just go away.
+
+redirect should interpret a path with a trailing / as /index.html
+
+ssi should change $cwd to the source document's location.
+
+Allow .throttle files in individual directories.
+
+Log-digesting scripts.
+
+Config web page.
+ Common errors:
+ Not realizing that -c overrides CGI_PATTERN instead of augmenting it.
+ Using a directory name for the -c pattern.
+
+- - - - - - - - - - 3.x - - - - - - - - - -
+
+Tasklets re-write.
+
+- - - - - - - - - - general - - - - - - - - - -
+
+Release process:
+ - update version number in version.h README INSTALL and
+ contrib/redhat-rpm/thttpd.spec
+ - do a tdiff and update the local installation
+ - do an rcstreeinfo, and check in all files
+ - make tar
+ - mv it to ..
+ - update version number in ../thttpd.html
+ - update ~acmeweb/updates.html
+ - mail announcement to thttpd-announce
--- /dev/null
+dnl
+dnl Improved version of AC_CHECK_LIB
+dnl
+dnl Thanks to John Hawkinson (jhawk@mit.edu)
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [,
+dnl ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
+dnl
+dnl results:
+dnl
+dnl LIBS
+dnl
+
+define(AC_LBL_CHECK_LIB,
+[AC_MSG_CHECKING([for $2 in -l$1])
+dnl Use a cache variable name containing both the library and function name,
+dnl because the test really is for library $1 defining function $2, not
+dnl just for library $1. Separate tests with the same $1 and different $2's
+dnl may have different results.
+ac_lib_var=`echo $1['_']$2['_']$5 | sed 'y%./+- %__p__%'`
+AC_CACHE_VAL(ac_cv_lbl_lib_$ac_lib_var,
+[ac_save_LIBS="$LIBS"
+LIBS="-l$1 $5 $LIBS"
+AC_TRY_LINK(dnl
+ifelse([$2], [main], , dnl Avoid conflicting decl of main.
+[/* Override any gcc2 internal prototype to avoid an error. */
+]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
+extern "C"
+#endif
+])dnl
+[/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $2();
+]),
+ [$2()],
+ eval "ac_cv_lbl_lib_$ac_lib_var=yes",
+ eval "ac_cv_lbl_lib_$ac_lib_var=no")
+LIBS="$ac_save_LIBS"
+])dnl
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], ,
+[changequote(, )dnl
+ ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+changequote([, ])dnl
+ AC_DEFINE_UNQUOTED($ac_tr_lib)
+ LIBS="-l$1 $LIBS"
+], [$3])
+else
+ AC_MSG_RESULT(no)
+ifelse([$4], , , [$4
+])dnl
+fi
+])
+
+dnl
+dnl AC_LBL_LIBRARY_NET
+dnl
+dnl This test is for network applications that need socket() and
+dnl gethostbyname() -ish functions. Under Solaris, those applications
+dnl need to link with "-lsocket -lnsl". Under IRIX, they need to link
+dnl with "-lnsl" but should *not* link with "-lsocket" because
+dnl libsocket.a breaks a number of things (for instance:
+dnl gethostbyname() under IRIX 5.2, and snoop sockets under most
+dnl versions of IRIX).
+dnl
+dnl Unfortunately, many application developers are not aware of this,
+dnl and mistakenly write tests that cause -lsocket to be used under
+dnl IRIX. It is also easy to write tests that cause -lnsl to be used
+dnl under operating systems where neither are necessary (or useful),
+dnl such as SunOS 4.1.4, which uses -lnsl for TLI.
+dnl
+dnl This test exists so that every application developer does not test
+dnl this in a different, and subtly broken fashion.
+
+dnl It has been argued that this test should be broken up into two
+dnl seperate tests, one for the resolver libraries, and one for the
+dnl libraries necessary for using Sockets API. Unfortunately, the two
+dnl are carefully intertwined and allowing the autoconf user to use
+dnl them independantly potentially results in unfortunate ordering
+dnl dependancies -- as such, such component macros would have to
+dnl carefully use indirection and be aware if the other components were
+dnl executed. Since other autoconf macros do not go to this trouble,
+dnl and almost no applications use sockets without the resolver, this
+dnl complexity has not been implemented.
+dnl
+dnl The check for libresolv is in case you are attempting to link
+dnl statically and happen to have a libresolv.a lying around (and no
+dnl libnsl.a).
+dnl
+AC_DEFUN(AC_LBL_LIBRARY_NET, [
+ # Most operating systems have gethostbyname() in the default searched
+ # libraries (i.e. libc):
+ AC_CHECK_FUNC(gethostbyname, ,
+ # Some OSes (eg. Solaris) place it in libnsl:
+ AC_LBL_CHECK_LIB(nsl, gethostbyname, ,
+ # Some strange OSes (SINIX) have it in libsocket:
+ AC_LBL_CHECK_LIB(socket, gethostbyname, ,
+ # Unfortunately libsocket sometimes depends on libnsl.
+ # AC_CHECK_LIB's API is essentially broken so the
+ # following ugliness is necessary:
+ AC_LBL_CHECK_LIB(socket, gethostbyname,
+ LIBS="-lsocket -lnsl $LIBS",
+ AC_CHECK_LIB(resolv, gethostbyname),
+ -lnsl))))
+ AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, ,
+ AC_LBL_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", ,
+ -lnsl)))
+ # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+ AC_CHECK_LIB(str, putmsg)
+ ])
+
+dnl
+dnl Checks to see if struct tm has the BSD tm_gmtoff member
+dnl
+dnl usage:
+dnl
+dnl AC_ACME_TM_GMTOFF
+dnl
+dnl results:
+dnl
+dnl HAVE_TM_GMTOFF (defined)
+dnl
+AC_DEFUN(AC_ACME_TM_GMTOFF,
+ [AC_MSG_CHECKING(if struct tm has tm_gmtoff member)
+ AC_CACHE_VAL(ac_cv_acme_tm_has_tm_gmtoff,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <time.h>],
+ [u_int i = sizeof(((struct tm *)0)->tm_gmtoff)],
+ ac_cv_acme_tm_has_tm_gmtoff=yes,
+ ac_cv_acme_tm_has_tm_gmtoff=no))
+ AC_MSG_RESULT($ac_cv_acme_tm_has_tm_gmtoff)
+ if test $ac_cv_acme_tm_has_tm_gmtoff = yes ; then
+ AC_DEFINE(HAVE_TM_GMTOFF)
+ fi])
+
+dnl
+dnl Checks to see if int64_t exists
+dnl
+dnl usage:
+dnl
+dnl AC_ACME_INT64T
+dnl
+dnl results:
+dnl
+dnl HAVE_INT64T (defined)
+dnl
+AC_DEFUN(AC_ACME_INT64T,
+ [AC_MSG_CHECKING(if int64_t exists)
+ AC_CACHE_VAL(ac_cv_acme_int64_t,
+ AC_TRY_COMPILE([
+# include <sys/types.h>],
+ [int64_t i64],
+ ac_cv_acme_int64_t=yes,
+ ac_cv_acme_int64_t=no))
+ AC_MSG_RESULT($ac_cv_acme_int64_t)
+ if test $ac_cv_acme_int64_t = yes ; then
+ AC_DEFINE(HAVE_INT64T)
+ fi])
+
+dnl
+dnl Checks to see if socklen_t exists
+dnl
+dnl usage:
+dnl
+dnl AC_ACME_SOCKLENT
+dnl
+dnl results:
+dnl
+dnl HAVE_SOCKLENT (defined)
+dnl
+AC_DEFUN(AC_ACME_SOCKLENT,
+ [AC_MSG_CHECKING(if socklen_t exists)
+ AC_CACHE_VAL(ac_cv_acme_socklen_t,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <sys/socket.h>],
+ [socklen_t slen],
+ ac_cv_acme_socklen_t=yes,
+ ac_cv_acme_socklen_t=no))
+ AC_MSG_RESULT($ac_cv_acme_socklen_t)
+ if test $ac_cv_acme_socklen_t = yes ; then
+ AC_DEFINE(HAVE_SOCKLENT)
+ fi])
--- /dev/null
+#!/bin/sh
+
+date=`date -u '+%a, %d %b %Y %H:%M:%S %Z'`
+
+cat << EOF
+Content-type: text/plain
+Expires: $date
+
+CGI printenv
+
+EOF
+
+echo 'Date:'
+date
+echo
+echo 'Id:'
+id
+echo
+echo 'Env:'
+printenv
+echo
+if [ "$CONTENT_LENGTH" != "" ] ; then
+ if [ "$CONTENT_LENGTH" -ne 0 ] ; then
+ echo 'Input:'
+ echo
+ dd bs=1 count=$CONTENT_LENGTH
+ echo
+ fi
+fi
--- /dev/null
+# Generated automatically from Makefile.in by configure.
+# Makefile for cgi-src
+#
+# Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+WEBDIR = $(prefix)/www
+CGIBINDIR = $(WEBDIR)/cgi-bin
+MANDIR = /usr/local/man
+
+CC = gcc
+CCOPT = -O2
+DEFS = -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1
+INCLS = -I..
+CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
+LDFLAGS =
+LIBS = -lcrypt
+NETLIBS =
+INSTALL = /usr/bin/install -c
+
+CLEANFILES = *.o redirect ssi phf
+
+
+
+.c.o:
+ @rm -f $@
+ $(CC) $(CFLAGS) -c $*.c
+
+all: redirect ssi phf
+
+redirect: redirect.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) redirect.o $(LIBS) -o redirect
+
+ssi: ssi.o ../match.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) ssi.o ../match.o $(LIBS) -o ssi
+
+ssi.o: ../match.h
+
+phf: phf.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) phf.o $(LIBS) -o phf
+
+strerror.o:
+ @rm -f strerror.o
+ @ln -s ../strerror.o
+ cd .. ; $(MAKE) $(MFLAGS) strerror.o
+
+install: all
+ -mkdir -p $(CGIBINDIR)
+ rm -f $(CGIBINDIR)/redirect
+ cp redirect $(CGIBINDIR)/redirect
+ rm -f $(MANDIR)/man8/redirect.8
+ cp redirect.8 $(MANDIR)/man8/redirect.8
+ rm -f $(CGIBINDIR)/ssi
+ cp ssi $(CGIBINDIR)/ssi
+ rm -f $(MANDIR)/man8/ssi.8
+ cp ssi.8 $(MANDIR)/man8/ssi.8
+ rm -f $(CGIBINDIR)/phf
+ cp phf $(CGIBINDIR)/phf
+
+clean:
+ rm -f $(CLEANFILES)
+
+distclean:
+ rm -f $(CLEANFILES) Makefile
--- /dev/null
+# Makefile for cgi-src
+#
+# Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+WEBDIR = $(prefix)/www
+CGIBINDIR = $(WEBDIR)/cgi-bin
+MANDIR = @mandir@
+
+CC = @CC@
+CCOPT = @V_CCOPT@
+DEFS = @DEFS@
+INCLS = -I..
+CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
+LDFLAGS = @LDFLAGS@ @V_STATICFLAG@
+LIBS = @LIBS@
+NETLIBS = @V_NETLIBS@
+INSTALL = @INSTALL@
+
+CLEANFILES = *.o redirect ssi phf
+
+@SET_MAKE@
+
+.c.o:
+ @rm -f $@
+ $(CC) $(CFLAGS) -c $*.c
+
+all: redirect ssi phf
+
+redirect: redirect.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) redirect.o $(LIBS) -o redirect
+
+ssi: ssi.o ../match.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) ssi.o ../match.o $(LIBS) -o ssi
+
+ssi.o: ../match.h
+
+phf: phf.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) phf.o $(LIBS) -o phf
+
+strerror.o:
+ @rm -f strerror.o
+ @ln -s ../strerror.o
+ cd .. ; $(MAKE) $(MFLAGS) strerror.o
+
+install: all
+ -mkdir -p $(CGIBINDIR)
+ rm -f $(CGIBINDIR)/redirect
+ cp redirect $(CGIBINDIR)/redirect
+ rm -f $(MANDIR)/man8/redirect.8
+ cp redirect.8 $(MANDIR)/man8/redirect.8
+ rm -f $(CGIBINDIR)/ssi
+ cp ssi $(CGIBINDIR)/ssi
+ rm -f $(MANDIR)/man8/ssi.8
+ cp ssi.8 $(MANDIR)/man8/ssi.8
+ rm -f $(CGIBINDIR)/phf
+ cp phf $(CGIBINDIR)/phf
+
+clean:
+ rm -f $(CLEANFILES)
+
+distclean:
+ rm -f $(CLEANFILES) Makefile
--- /dev/null
+/* phf - cracker trap
+**
+** Old distributions of the NCSA and Apache web servers included a
+** version of the phf program that had a bug. The program could
+** easily be made to run arbitrary shell commands. There is no real
+** legitimate use for phf, so any attempts to run it must be considered
+** to be attacks. Accordingly, this version of phf logs the attack
+** and then returns a page indicating that phf doesn't exist.
+**
+**
+** Copyright © 1996 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "config.h"
+
+static char* argv0;
+
+int
+main( int argc, char* argv[] )
+ {
+ char* cp;
+
+ argv0 = argv[0];
+ cp = strrchr( argv0, '/' );
+ if ( cp != (char*) 0 )
+ ++cp;
+ else
+ cp = argv0;
+ openlog( cp, LOG_NDELAY|LOG_PID, LOG_FACILITY );
+ syslog( LOG_CRIT, "phf CGI probe from %s", getenv( "REMOTE_ADDR" ) );
+ (void) printf( "\
+Content-type: text/html\n\
+Status: 404/html\n\
+\n\
+<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n\
+<BODY><H2>404 Not Found</H2>\n\
+The requested object does not exist on this server.\n\
+The link you followed is either outdated, inaccurate,\n\
+or the server has been instructed not to let you have it.\n\
+</BODY></HTML>\n" );
+ exit( 0 );
+ }
--- /dev/null
+.TH redirect 8 "23 September 1995"
+.SH NAME
+redirect - simple redirection CGI program
+.SH SYNOPSIS
+.B redirect
+.SH DESCRIPTION
+.PP
+Three steps to set up a redirection:
+.PP
+1. Make sure your web server is set up to allow CGI programs.
+.PP
+2. Make a symbolic link from the file or directory you want to redirect,
+pointing at this program in the CGI bin directory.
+.PP
+3. Add an entry to the file ".redirects" in the directory where your
+http server runs CGI programs. For most servers, this is the
+directory where the given CGI program lives. The format of the
+file is a bunch of lines with a filename, whitespace, and the new
+URL. For example:
+.nf
+ /test/oldfile.html http://www.acme.com/test/newfile.html
+.fi
+The easiest way to figure out precisely what filename to put into .redirects
+is to set up the symlink and then click on it.
+You'll get back a "404 Not Found" page which includes the filename
+as received by the redirect program, and that's what you want to use.
+.PP
+You can also add a wildcard specification to redirect whole groups of files.
+For example:
+.nf
+ /wildtest/* http://www.acme.com/test-
+.fi
+will cause an access to the /wildtest/somefile.html to be redirected to
+http://www.acme.com/test-somefile.html. (Note that the asterisk need not
+be preceded by a slash.)
+.PP
+Note: this is designed for thttpd (http://www.acme.com/software/thttpd/)
+and using it with other web servers may require some hacking. A possible
+gotcha is with the symbolic link from the old file pointing at this
+script - servers other than thttpd may not allow that link to be run
+as a CGI program, because they don't check the link to see that it
+points into the allowed CGI directory.
+.SH "SEE ALSO"
+thttpd(8)
+.SH "BUGS / DEFICIENCIES"
+.PP
+It would be really cool to have this program look for
+the .redirects file in the same directory as the file being redirected,
+instead of in the binaries directory. Unfortunately, this appears
+to be impossible with the information CGI gives, plus the non-standardized
+but widespread practice of running CGI programs in the directory where
+the binary lives. Perhaps CGI 1.2 will address this.
+.PP
+The wildcard mechanism is very primitive.
+In particular, any characters that follow the asterisk are blithely
+ignored.
+.SH AUTHOR
+Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+All rights reserved.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
--- /dev/null
+/* redirect - simple redirection CGI program
+**
+** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+/* Three steps to set up a redirection:
+** 1. Make sure your web server is set up to allow CGI programs.
+** 2. Make a symbolic link from the file you want to redirect,
+** pointing at this program in the CGI bin directory.
+** 3. Add an entry to the file ".redirects" in the directory where your
+** http server runs CGI programs. For most servers, this is the
+** directory where the given CGI program lives. The format of the
+** file is a bunch of lines with a filename, whitespace, and the new
+** URL. For example:
+
+/test/oldfile.html http://www.acme.com/test/newfile.html
+
+** The easiest way to figure out precisely what filename to put into
+** .redirects is to set up the symlink and then click on it. You'll get
+** back a "404 Not Found" page which includes the filename as received by
+** the redirect program, and that's what you want to use.
+**
+** Note: this is designed for thttpd (http://www.acme.com/software/thttpd/)
+** and using it with other web servers may require some hacking. A possible
+** gotcha is with the symbolic link from the old file pointing at this
+** script - servers other than thttpd may not allow that link to be run
+** as a CGI program, because they don't check the link to see that it
+** points into the allowed CGI directory.
+**
+** Note two: It would be really cool to have this program look for
+** the .redirects file in the same directory as the file being redirected,
+** instead of in the binaries directory. Unfortunately, this appears
+** to be impossible with the information CGI gives, plus the non-standardized
+** but widespread practice of running CGI programs in the directory where
+** the binary lives. Perhaps CGI 1.2 will address this.
+*/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+
+
+static char* argv0;
+
+
+static void
+internal_error( char* reason )
+ {
+ char* title = "500 Internal Error";
+
+ (void) printf( "\
+Status: %s\n\
+Content-type: text/html\n\
+\n\
+<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
+<BODY><H2>%s</H2>\n\
+Something unusual went wrong during a redirection request:\n\
+<BLOCKQUOTE>\n\
+%s\n\
+</BLOCKQUOTE>\n\
+</BODY></HTML>\n", title, title, title, reason );
+ }
+
+
+static void
+not_found( char* script_name )
+ {
+ char* title = "404 Not Found";
+
+ (void) printf( "\
+Status: %s\n\
+Content-type: text/html\n\
+\n\
+<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
+<BODY><H2>%s</H2>\n\
+The requested filename, %s, is set up to be redirected to another URL;\n\
+however, the new URL has not yet been specified.\n\
+</BODY></HTML>\n", title, title, title, script_name );
+ }
+
+
+static void
+moved( char* script_name, char* url )
+ {
+ char* title = "Moved";
+
+ (void) printf( "\
+Location: %s\n\
+Content-type: text/html\n\
+\n\
+<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
+<BODY><H2>%s</H2>\n\
+The requested filename, %s, has moved to a new URL:\n\
+<A HREF=\"%s\">%s</A>.\n\
+</BODY></HTML>\n", url, title, title, script_name, url, url );
+ }
+
+
+int
+main( int argc, char** argv )
+ {
+ char* script_name;
+ char* path_info;
+ char* cp;
+ FILE* fp;
+ char *star;
+ char buf[5000], file[5000], url[5000];
+
+ argv0 = argv[0];
+
+ /* Get the name that we were run as, which is the filename being
+ ** redirected.
+ */
+ script_name = getenv( "SCRIPT_NAME" );
+ if ( script_name == (char*) 0 )
+ {
+ internal_error( "Couldn't get SCRIPT_NAME environment variable." );
+ exit( 1 );
+ }
+
+ /* Append the PATH_INFO, if any. This allows redirection of whole
+ ** directories.
+ */
+ path_info = getenv( "PATH_INFO" );
+ if ( path_info != (char*) 0 )
+ {
+ cp = (char*) malloc( strlen( script_name ) + strlen( path_info ) + 1 );
+ if ( cp == (char*) 0 )
+ {
+ internal_error( "Out of memory." );
+ exit( 1 );
+ }
+ (void) sprintf( cp, "%s%s", script_name, path_info );
+ script_name = cp;
+ }
+
+ /* Open the redirects file. */
+ fp = fopen( ".redirects", "r" );
+ if ( fp == (FILE*) 0 )
+ {
+ internal_error( "Couldn't open .redirects file." );
+ exit( 1 );
+ }
+
+ /* Search the file for a matching entry. */
+ while ( fgets( buf, sizeof(buf), fp ) != (char*) 0 )
+ {
+ /* Remove comments. */
+ cp = strchr( buf, '#' );
+ if ( cp != (char*) 0 )
+ *cp = '\0';
+ /* Skip leading whitespace. */
+ cp = buf;
+ cp += strspn( cp, " \t" );
+ /* Check for blank line. */
+ if ( *cp != '\0' )
+ {
+ /* Parse line. */
+ if ( sscanf( cp, "%[^ \t\n] %[^ \t\n]", file, url ) == 2 )
+ {
+ /* Check for wildcard match. */
+ star = strchr( file, '*' );
+ if ( star != (char*) 0 )
+ {
+ /* Check for leading match. */
+ if ( strncmp( file, script_name, star - file ) == 0 )
+ {
+ /* Got it; put together the full name. */
+ strcat( url, script_name + ( star - file ) );
+ /* XXX Whack the script_name, too? */
+ moved( script_name, url );
+ exit( 0 );
+ }
+ }
+ /* Check for exact match. */
+ if ( strcmp( file, script_name ) == 0 )
+ {
+ /* Got it. */
+ moved( script_name, url );
+ exit( 0 );
+ }
+ }
+ }
+ }
+
+ /* No match found. */
+ not_found( script_name );
+ exit( 1 );
+ }
--- /dev/null
+.TH ssi 8 "18 October 1995"
+.SH NAME
+ssi - server-side-includes CGI program
+.SH SYNOPSIS
+.B ssi
+.SH DESCRIPTION
+.PP
+This is an external CGI program that gives you the same functionality
+as the built-in server-side-includes feature in some HTTP daemons.
+It is written for use with thttpd(8), but should be easy to adapt
+to other systems.
+.PP
+To use this program, first make sure it is installed in your server's
+CGI area, and that CGI is enabled.
+Then set up your URLs with the path to the document you want parsed
+as the "pathinfo".
+That's the part of the URL that comes after the CGI program name.
+For example, if the URL to this program is:
+.nf
+ http://www.acme.com/cgi-bin/ssi
+.fi
+and the url for your document is:
+.nf
+ http://www.acme.com/users/wecoyote/doc.html
+.fi
+then the compound URL that gives you the document filtered through the
+program would be:
+.nf
+ http://www.acme.com/cgi-bin/ssi/users/wecoyote/doc.html
+.fi
+.PP
+The format description below is adapted from
+http://hoohoo.ncsa.uiuc.edu/docs/tutorials/includes.html
+.SH "INCLUDE FORMAT"
+.PP
+All directives are formatted as SGML comments within the document.
+This is in case the document should ever find itself in the client's
+hands unparsed.
+Each directive has the following format:
+.nf
+ <!--#command tag1="value1" tag2="value2" -->
+.fi
+Each command takes different arguments, most only accept one tag at a time.
+Here is a breakdown of the commands and their associated tags:
+.IP * 4
+.BR config :
+The config directive controls various aspects of the file parsing.
+There are two valid tags:
+.IP o 8
+.BR timefmt :
+gives the server a new format to use when providing dates.
+This is a string compatible with the strftime library call.
+.IP o 8
+.BR sizefmt :
+determines the formatting to be used when displaying the
+size of a file.
+Valid choices are bytes, for a formatted byte count
+(formatted as 1,234,567), or abbrev for an abbreviated version
+displaying the number of kilobytes or megabytes the file occupies.
+.IP * 4
+.BR include :
+Inserts the text of another document into the parsed document.
+The inserted file is parsed recursively, so it can contain
+server-side-include directives too.
+This command accepts two tags:
+.IP o 8
+.BR virtual :
+Gives a virtual path to a document on the server.
+.IP o 8
+.BR file :
+Gives a pathname relative to the current directory. ../ cannot
+be used in this pathname, nor can absolute paths be used.
+.IP * 4
+.BR echo :
+Prints the value of one of the include variables (defined below).
+Any dates are printed subject to the currently configured timefmt.
+The only valid tag to this command is var, whose value is the name of the
+variable you wish to echo.
+.IP * 4
+.BR fsize :
+prints the size of the specified file,
+subject to the sizefmt parameter to the config command.
+Valid tags are the same as with the include command.
+.IP * 4
+.BR flastmod :
+prints the last modification date of the specified file, subject
+to the formatting preference given by the timefmt parameter to config.
+Valid tags are the same as with the include command.
+.SH VARIABLES
+.PP
+A number of variables are made available to parsed documents.
+In addition to
+the CGI variable set, the following variables are made available:
+.IP * 4
+.BR DOCUMENT_NAME :
+The current filename.
+.IP * 4
+.BR DOCUMENT_URI :
+The virtual path to this document (such as /~robm/foo.shtml).
+.IP * 4
+.BR QUERY_STRING_UNESCAPED :
+The unescaped version of any search query the client sent.
+.IP * 4
+.BR DATE_LOCAL :
+The current date, local time zone.
+Subject to the timefmt parameter to the config command.
+.IP * 4
+.BR DATE_GMT :
+Same as DATE_LOCAL but in Greenwich mean time.
+.IP * 4
+.BR LAST_MODIFIED :
+The last modification date of the current document.
+Subject to timefmt like the others.
+.SH "BUGS / DEFICIENCIES"
+.PP
+Does not implement the "exec" directive.
+Actually, I consider this neither a bug nor a deficiency, but some may.
+.SH "SEE ALSO"
+thttpd(8), strftime(3)
+.SH AUTHOR
+Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+All rights reserved.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
--- /dev/null
+/* ssi - server-side-includes CGI program
+**
+** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "config.h"
+#include "match.h"
+
+
+#define ST_GROUND 0
+#define ST_LESSTHAN 1
+#define ST_BANG 2
+#define ST_MINUS1 3
+#define ST_MINUS2 4
+
+
+static void read_file( char* vfilename, char* filename, FILE* fp );
+
+
+static char* argv0;
+static char* url;
+
+static char timefmt[100];
+static int sizefmt;
+#define SF_BYTES 0
+#define SF_ABBREV 1
+static struct stat sb;
+
+
+static void
+internal_error( char* reason )
+ {
+ char* title = "500 Internal Error";
+
+ (void) printf( "\
+<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
+<BODY><H2>%s</H2>\n\
+Something unusual went wrong during a server-side-includes request:\n\
+<BLOCKQUOTE>\n\
+%s\n\
+</BLOCKQUOTE>\n\
+</BODY></HTML>\n", title, title, reason );
+ }
+
+
+static void
+not_found( char* filename )
+ {
+ char* title = "404 Not Found";
+
+ (void) printf( "\
+<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
+<BODY><H2>%s</H2>\n\
+The requested server-side-includes filename, %s,\n\
+does not seem to exist.\n\
+</BODY></HTML>\n", title, title, filename );
+ }
+
+
+static void
+not_found2( char* directive, char* tag, char* filename2 )
+ {
+ char* title = "Not Found";
+
+ (void) printf( "\
+<HR><H2>%s</H2>\n\
+The filename requested in a %s %s directive, %s,\n\
+does not seem to exist.\n\
+<HR>\n", title, directive, tag, filename2 );
+ }
+
+
+static void
+not_permitted( char* directive, char* tag, char* val )
+ {
+ char* title = "Not Permitted";
+
+ (void) printf( "\
+<HR><H2>%s</H2>\n\
+The filename requested in the %s %s=%s directive\n\
+may not be fetched.\n\
+<HR>\n", title, directive, tag, val );
+ }
+
+
+static void
+unknown_directive( char* filename, char* directive )
+ {
+ char* title = "Unknown Directive";
+
+ (void) printf( "\
+<HR><H2>%s</H2>\n\
+The requested server-side-includes filename, %s,\n\
+tried to use an unknown directive, %s.\n\
+<HR>\n", title, filename, directive );
+ }
+
+
+static void
+unknown_tag( char* filename, char* directive, char* tag )
+ {
+ char* title = "Unknown Tag";
+
+ (void) printf( "\
+<HR><H2>%s</H2>\n\
+The requested server-side-includes filename, %s,\n\
+tried to use the directive %s with an unknown tag, %s.\n\
+<HR>\n", title, filename, directive, tag );
+ }
+
+
+static void
+unknown_value( char* filename, char* directive, char* tag, char* val )
+ {
+ char* title = "Unknown Value";
+
+ (void) printf( "\
+<HR><H2>%s</H2>\n\
+The requested server-side-includes filename, %s,\n\
+tried to use the directive %s %s with an unknown value, %s.\n\
+<HR>\n", title, filename, directive, tag, val );
+ }
+
+
+static int
+get_filename( char* vfilename, char* filename, char* directive, char* tag, char* val, char* fn, int fnsize )
+ {
+ int vl, fl;
+ char* cp;
+
+ /* Used for the various commands that accept a file name.
+ ** These commands accept two tags:
+ ** virtual
+ ** Gives a virtual path to a document on the server.
+ ** file
+ ** Gives a pathname relative to the current directory. ../ cannot
+ ** be used in this pathname, nor can absolute paths be used.
+ */
+ vl = strlen( vfilename );
+ fl = strlen( filename );
+ if ( strcmp( tag, "virtual" ) == 0 )
+ {
+ if ( strstr( val, "../" ) != (char*) 0 )
+ {
+ not_permitted( directive, tag, val );
+ return -1;
+ }
+ /* Figure out root using difference between vfilename and filename. */
+ if ( vl > fl ||
+ strcmp( vfilename, &filename[fl - vl] ) != 0 )
+ return -1;
+ if ( fl - vl + strlen( val ) >= fnsize )
+ return -1;
+ (void) strncpy( fn, filename, fl - vl );
+ (void) strcpy( &fn[fl - vl], val );
+ }
+ else if ( strcmp( tag, "file" ) == 0 )
+ {
+ if ( val[0] == '/' || strstr( val, "../" ) != (char*) 0 )
+ {
+ not_permitted( directive, tag, val );
+ return -1;
+ }
+ if ( fl + 1 + strlen( val ) >= fnsize )
+ return -1;
+ (void) strcpy( fn, filename );
+ cp = strrchr( fn, '/' );
+ if ( cp == (char*) 0 )
+ {
+ cp = &fn[strlen( fn )];
+ *cp = '/';
+ }
+ (void) strcpy( ++cp, val );
+ }
+ else
+ {
+ unknown_tag( filename, directive, tag );
+ return -1;
+ }
+ return 0;
+ }
+
+
+static int
+check_filename( char* filename )
+ {
+ static int inited = 0;
+ static char* cgi_pattern;
+ int fnl;
+ char* cp;
+ char* dirname;
+ char* authname;
+ struct stat sb2;
+ int r;
+
+ if ( ! inited )
+ {
+ /* Get the cgi pattern. */
+ cgi_pattern = getenv( "CGI_PATTERN" );
+#ifdef CGI_PATTERN
+ if ( cgi_pattern == (char*) 0 )
+ cgi_pattern = CGI_PATTERN;
+#endif /* CGI_PATTERN */
+ inited = 1;
+ }
+
+ /* ../ is not permitted. */
+ if ( strstr( filename, "../" ) != (char*) 0 )
+ return 0;
+
+#ifdef AUTH_FILE
+ /* Ensure that we are not reading a basic auth password file. */
+ fnl = strlen(filename);
+ if ( strcmp( filename, AUTH_FILE ) == 0 ||
+ ( fnl >= sizeof(AUTH_FILE) &&
+ strcmp( &filename[fnl - sizeof(AUTH_FILE) + 1], AUTH_FILE ) == 0 &&
+ filename[fnl - sizeof(AUTH_FILE)] == '/' ) )
+ return 0;
+
+ /* Check for an auth file in the same directory. We can't do an actual
+ ** auth password check here because CGI programs are not given the
+ ** authorization header, for security reasons. So instead we just
+ ** prohibit access to all auth-protected files.
+ */
+ dirname = strdup( filename );
+ if ( dirname == (char*) 0 )
+ return 0; /* out of memory */
+ cp = strrchr( dirname, '/' );
+ if ( cp == (char*) 0 )
+ (void) strcpy( dirname, "." );
+ else
+ *cp = '\0';
+ authname = malloc( strlen( dirname ) + 1 + sizeof(AUTH_FILE) );
+ if ( authname == (char*) 0 )
+ return 0; /* out of memory */
+ (void) sprintf( authname, "%s/%s", dirname, AUTH_FILE );
+ r = stat( authname, &sb2 );
+ free( dirname );
+ free( authname );
+ if ( r == 0 )
+ return 0;
+#endif /* AUTH_FILE */
+
+ /* Ensure that we are not reading a CGI file. */
+ if ( cgi_pattern != (char*) 0 && match( cgi_pattern, filename ) )
+ return 0;
+
+ return 1;
+ }
+
+
+static void
+show_time( time_t t, int gmt )
+ {
+ struct tm* tmP;
+ char tbuf[500];
+
+ if ( gmt )
+ tmP = gmtime( &t );
+ else
+ tmP = localtime( &t );
+ if ( strftime( tbuf, sizeof(tbuf), timefmt, tmP ) > 0 )
+ (void) fputs( tbuf, stdout );
+ }
+
+
+static void
+show_size( off_t size )
+ {
+ switch ( sizefmt )
+ {
+ case SF_BYTES:
+ (void) printf( "%ld", (long) size ); /* spec says should have commas */
+ break;
+ case SF_ABBREV:
+ if ( size < 1024 )
+ (void) printf( "%ld", (long) size );
+ else if ( size < 1024 )
+ (void) printf( "%ldK", (long) size / 1024L );
+ else if ( size < 1024*1024 )
+ (void) printf( "%ldM", (long) size / (1024L*1024L) );
+ else
+ (void) printf( "%ldG", (long) size / (1024L*1024L*1024L) );
+ break;
+ }
+ }
+
+
+static void
+do_config( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
+ {
+ /* The config directive controls various aspects of the file parsing.
+ ** There are two valid tags:
+ ** timefmt
+ ** Gives the server a new format to use when providing dates. This
+ ** is a string compatible with the strftime library call.
+ ** sizefmt
+ ** Determines the formatting to be used when displaying the size of
+ ** a file. Valid choices are bytes, for a formatted byte count
+ ** (formatted as 1,234,567), or abbrev for an abbreviated version
+ ** displaying the number of kilobytes or megabytes the file occupies.
+ */
+
+ if ( strcmp( tag, "timefmt" ) == 0 )
+ {
+ (void) strncpy( timefmt, val, sizeof(timefmt) - 1 );
+ timefmt[sizeof(timefmt) - 1] = '\0';
+ }
+ else if ( strcmp( tag, "sizefmt" ) == 0 )
+ {
+ if ( strcmp( val, "bytes" ) == 0 )
+ sizefmt = SF_BYTES;
+ else if ( strcmp( val, "abbrev" ) == 0 )
+ sizefmt = SF_ABBREV;
+ else
+ unknown_value( filename, directive, tag, val );
+ }
+ else
+ unknown_tag( filename, directive, tag );
+ }
+
+
+static void
+do_include( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
+ {
+ char vfilename2[1000];
+ char filename2[1000];
+ FILE* fp2;
+
+ /* Inserts the text of another document into the parsed document. */
+
+ if ( get_filename(
+ vfilename, filename, directive, tag, val, filename2,
+ sizeof(filename2) ) < 0 )
+ return;
+
+ if ( ! check_filename( filename2 ) )
+ {
+ not_permitted( directive, tag, filename2 );
+ return;
+ }
+
+ fp2 = fopen( filename2, "r" );
+ if ( fp2 == (FILE*) 0 )
+ {
+ not_found2( directive, tag, filename2 );
+ return;
+ }
+
+ if ( strcmp( tag, "virtual" ) == 0 )
+ {
+ if ( strlen( val ) < sizeof( vfilename2 ) )
+ (void) strcpy( vfilename2, val );
+ else
+ (void) strcpy( vfilename2, filename2 ); /* same size, has to fit */
+ }
+ else
+ {
+ if ( strlen( vfilename ) + 1 + strlen( val ) < sizeof(vfilename2) )
+ {
+ char* cp;
+ (void) strcpy( vfilename2, vfilename );
+ cp = strrchr( vfilename2, '/' );
+ if ( cp == (char*) 0 )
+ {
+ cp = &vfilename2[strlen( vfilename2 )];
+ *cp = '/';
+ }
+ (void) strcpy( ++cp, val );
+ }
+ else
+ (void) strcpy( vfilename2, filename2 ); /* same size, has to fit */
+ }
+
+ read_file( vfilename2, filename2, fp2 );
+ (void) fclose( fp2 );
+ }
+
+
+static void
+do_echo( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
+ {
+ char* cp;
+ time_t t;
+
+ /* Prints the value of one of the include variables. Any dates are
+ ** printed subject to the currently configured timefmt. The only valid
+ ** tag is var, whose value is the name of the variable you wish to echo.
+ */
+
+ if ( strcmp( tag, "var" ) != 0 )
+ unknown_tag( filename, directive, tag );
+ else
+ {
+ if ( strcmp( val, "DOCUMENT_NAME" ) == 0 )
+ {
+ /* The current filename. */
+ (void) fputs( filename, stdout );
+ }
+ else if ( strcmp( val, "DOCUMENT_URI" ) == 0 )
+ {
+ /* The virtual path to this file (such as /~robm/foo.shtml). */
+ (void) fputs( vfilename, stdout );
+ }
+ else if ( strcmp( val, "QUERY_STRING_UNESCAPED" ) == 0 )
+ {
+ /* The unescaped version of any search query the client sent. */
+ cp = getenv( "QUERY_STRING" );
+ if ( cp != (char*) 0 )
+ (void) fputs( cp, stdout );
+ }
+ else if ( strcmp( val, "DATE_LOCAL" ) == 0 )
+ {
+ /* The current date, local time zone. */
+ t = time( (time_t*) 0 );
+ show_time( t, 0 );
+ }
+ else if ( strcmp( val, "DATE_GMT" ) == 0 )
+ {
+ /* Same as DATE_LOCAL but in Greenwich mean time. */
+ t = time( (time_t*) 0 );
+ show_time( t, 1 );
+ }
+ else if ( strcmp( val, "LAST_MODIFIED" ) == 0 )
+ {
+ /* The last modification date of the current document. */
+ if ( fstat( fileno( fp ), &sb ) >= 0 )
+ show_time( sb.st_mtime, 0 );
+ }
+ else
+ {
+ /* Try an environment variable. */
+ cp = getenv( val );
+ if ( cp == (char*) 0 )
+ unknown_value( filename, directive, tag, val );
+ else
+ (void) fputs( cp, stdout );
+ }
+ }
+ }
+
+
+static void
+do_fsize( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
+ {
+ char filename2[1000];
+
+ /* Prints the size of the specified file. */
+
+ if ( get_filename(
+ vfilename, filename, directive, tag, val, filename2,
+ sizeof(filename2) ) < 0 )
+ return;
+ if ( stat( filename2, &sb ) < 0 )
+ {
+ not_found2( directive, tag, filename2 );
+ return;
+ }
+ show_size( sb.st_size );
+ }
+
+
+static void
+do_flastmod( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
+ {
+ char filename2[1000];
+
+ /* Prints the last modification date of the specified file. */
+
+ if ( get_filename(
+ vfilename, filename, directive, tag, val, filename2,
+ sizeof(filename2) ) < 0 )
+ return;
+ if ( stat( filename2, &sb ) < 0 )
+ {
+ not_found2( directive, tag, filename2 );
+ return;
+ }
+ show_time( sb.st_mtime, 0 );
+ }
+
+
+static void
+parse( char* vfilename, char* filename, FILE* fp, char* str )
+ {
+ char* directive;
+ char* cp;
+ int ntags;
+ char* tags[200];
+ int dirn;
+#define DI_CONFIG 0
+#define DI_INCLUDE 1
+#define DI_ECHO 2
+#define DI_FSIZE 3
+#define DI_FLASTMOD 4
+ int i;
+ char* val;
+
+ directive = str;
+ directive += strspn( directive, " \t\n\r" );
+
+ ntags = 0;
+ cp = directive;
+ for (;;)
+ {
+ cp = strpbrk( cp, " \t\n\r\"" );
+ if ( cp == (char*) 0 )
+ break;
+ if ( *cp == '"' )
+ {
+ cp = strpbrk( cp + 1, "\"" );
+ ++cp;
+ if ( *cp == '\0' )
+ break;
+ }
+ *cp++ = '\0';
+ cp += strspn( cp, " \t\n\r" );
+ if ( *cp == '\0' )
+ break;
+ if ( ntags < sizeof(tags)/sizeof(*tags) )
+ tags[ntags++] = cp;
+ }
+
+ if ( strcmp( directive, "config" ) == 0 )
+ dirn = DI_CONFIG;
+ else if ( strcmp( directive, "include" ) == 0 )
+ dirn = DI_INCLUDE;
+ else if ( strcmp( directive, "echo" ) == 0 )
+ dirn = DI_ECHO;
+ else if ( strcmp( directive, "fsize" ) == 0 )
+ dirn = DI_FSIZE;
+ else if ( strcmp( directive, "flastmod" ) == 0 )
+ dirn = DI_FLASTMOD;
+ else
+ {
+ unknown_directive( filename, directive );
+ return;
+ }
+
+ for ( i = 0; i < ntags; ++i )
+ {
+ if ( i > 0 )
+ putchar( ' ' );
+ val = strchr( tags[i], '=' );
+ if ( val == (char*) 0 )
+ val = "";
+ else
+ *val++ = '\0';
+ if ( *val == '"' && val[strlen( val ) - 1] == '"' )
+ {
+ val[strlen( val ) - 1] = '\0';
+ ++val;
+ }
+ switch( dirn )
+ {
+ case DI_CONFIG:
+ do_config( vfilename, filename, fp, directive, tags[i], val );
+ break;
+ case DI_INCLUDE:
+ do_include( vfilename, filename, fp, directive, tags[i], val );
+ break;
+ case DI_ECHO:
+ do_echo( vfilename, filename, fp, directive, tags[i], val );
+ break;
+ case DI_FSIZE:
+ do_fsize( vfilename, filename, fp, directive, tags[i], val );
+ break;
+ case DI_FLASTMOD:
+ do_flastmod( vfilename, filename, fp, directive, tags[i], val );
+ break;
+ }
+ }
+ }
+
+
+static void
+slurp( char* vfilename, char* filename, FILE* fp )
+ {
+ char buf[1000];
+ int i;
+ int state;
+ int ich;
+
+ /* Now slurp in the rest of the comment from the input file. */
+ i = 0;
+ state = ST_GROUND;
+ while ( ( ich = getc( fp ) ) != EOF )
+ {
+ switch ( state )
+ {
+ case ST_GROUND:
+ if ( ich == '-' )
+ state = ST_MINUS1;
+ break;
+ case ST_MINUS1:
+ if ( ich == '-' )
+ state = ST_MINUS2;
+ else
+ state = ST_GROUND;
+ break;
+ case ST_MINUS2:
+ if ( ich == '>' )
+ {
+ buf[i - 2] = '\0';
+ parse( vfilename, filename, fp, buf );
+ return;
+ }
+ else if ( ich != '-' )
+ state = ST_GROUND;
+ break;
+ }
+ if ( i < sizeof(buf) - 1 )
+ buf[i++] = (char) ich;
+ }
+ }
+
+
+static void
+read_file( char* vfilename, char* filename, FILE* fp )
+ {
+ int ich;
+ int state;
+
+ /* Copy it to output, while running a state-machine to look for
+ ** SSI directives.
+ */
+ state = ST_GROUND;
+ while ( ( ich = getc( fp ) ) != EOF )
+ {
+ switch ( state )
+ {
+ case ST_GROUND:
+ if ( ich == '<' )
+ { state = ST_LESSTHAN; continue; }
+ break;
+ case ST_LESSTHAN:
+ if ( ich == '!' )
+ { state = ST_BANG; continue; }
+ else
+ { state = ST_GROUND; putchar( '<' ); }
+ break;
+ case ST_BANG:
+ if ( ich == '-' )
+ { state = ST_MINUS1; continue; }
+ else
+ { state = ST_GROUND; (void) fputs ( "<!", stdout ); }
+ break;
+ case ST_MINUS1:
+ if ( ich == '-' )
+ { state = ST_MINUS2; continue; }
+ else
+ { state = ST_GROUND; (void) fputs ( "<!-", stdout ); }
+ break;
+ case ST_MINUS2:
+ if ( ich == '#' )
+ {
+ slurp( vfilename, filename, fp );
+ state = ST_GROUND;
+ continue;
+ }
+ else
+ { state = ST_GROUND; (void) fputs ( "<!--", stdout ); }
+ break;
+ }
+ putchar( (char) ich );
+ }
+ }
+
+
+int
+main( int argc, char** argv )
+ {
+ char* script_name;
+ char* path_info;
+ char* path_translated;
+ FILE* fp;
+
+ argv0 = argv[0];
+
+ /* Default formats. */
+ (void) strcpy( timefmt, "%a %b %e %T %Z %Y" );
+ sizefmt = SF_BYTES;
+
+ /* The MIME type has to be text/html. */
+ (void) fputs( "Content-type: text/html\n\n", stdout );
+
+ /* Get the name that we were run as. */
+ script_name = getenv( "SCRIPT_NAME" );
+ if ( script_name == (char*) 0 )
+ {
+ internal_error( "Couldn't get SCRIPT_NAME environment variable." );
+ exit( 1 );
+ }
+
+ /* Append the PATH_INFO, if any, to get the full URL. */
+ path_info = getenv( "PATH_INFO" );
+ if ( path_info == (char*) 0 )
+ path_info = "";
+ url = (char*) malloc( strlen( script_name ) + strlen( path_info ) + 1 );
+ if ( url == (char*) 0 )
+ {
+ internal_error( "Out of memory." );
+ exit( 1 );
+ }
+ (void) sprintf( url, "%s%s", script_name, path_info );
+
+ /* Get the name of the file to parse. */
+ path_translated = getenv( "PATH_TRANSLATED" );
+ if ( path_translated == (char*) 0 )
+ {
+ internal_error( "Couldn't get PATH_TRANSLATED environment variable." );
+ exit( 1 );
+ }
+
+ if ( ! check_filename( path_translated ) )
+ {
+ not_permitted( "initial", "PATH_TRANSLATED", path_translated );
+ exit( 1 );
+ }
+
+ /* Open it. */
+ fp = fopen( path_translated, "r" );
+ if ( fp == (FILE*) 0 )
+ {
+ not_found( path_translated );
+ exit( 1 );
+ }
+
+ /* Read and handle the file. */
+ read_file( path_info, path_translated, fp );
+
+ (void) fclose( fp );
+ exit( 0 );
+ }
--- /dev/null
+# 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. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+ac_cv_acme_int64_t=${ac_cv_acme_int64_t='yes'}
+ac_cv_acme_socklen_t=${ac_cv_acme_socklen_t='yes'}
+ac_cv_acme_tm_has_tm_gmtoff=${ac_cv_acme_tm_has_tm_gmtoff='yes'}
+ac_cv_extern__progname=${ac_cv_extern__progname='yes'}
+ac_cv_func_atoll=${ac_cv_func_atoll='yes'}
+ac_cv_func_crypt=${ac_cv_func_crypt='no'}
+ac_cv_func_daemon=${ac_cv_func_daemon='yes'}
+ac_cv_func_gai_strerror=${ac_cv_func_gai_strerror='yes'}
+ac_cv_func_getaddrinfo=${ac_cv_func_getaddrinfo='yes'}
+ac_cv_func_gethostbyname=${ac_cv_func_gethostbyname='yes'}
+ac_cv_func_getnameinfo=${ac_cv_func_getnameinfo='yes'}
+ac_cv_func_getpagesize=${ac_cv_func_getpagesize='yes'}
+ac_cv_func_hstrerror=${ac_cv_func_hstrerror='yes'}
+ac_cv_func_kqueue=${ac_cv_func_kqueue='no'}
+ac_cv_func_mmap_fixed_mapped=${ac_cv_func_mmap_fixed_mapped='yes'}
+ac_cv_func_poll=${ac_cv_func_poll='yes'}
+ac_cv_func_select=${ac_cv_func_select='yes'}
+ac_cv_func_setlogin=${ac_cv_func_setlogin='no'}
+ac_cv_func_setsid=${ac_cv_func_setsid='yes'}
+ac_cv_func_sigset=${ac_cv_func_sigset='yes'}
+ac_cv_func_socket=${ac_cv_func_socket='yes'}
+ac_cv_func_strerror=${ac_cv_func_strerror='yes'}
+ac_cv_func_vsnprintf=${ac_cv_func_vsnprintf='yes'}
+ac_cv_func_waitpid=${ac_cv_func_waitpid='yes'}
+ac_cv_header_dirent_dirent_h=${ac_cv_header_dirent_dirent_h='yes'}
+ac_cv_header_fcntl_h=${ac_cv_header_fcntl_h='yes'}
+ac_cv_header_grp_h=${ac_cv_header_grp_h='yes'}
+ac_cv_header_memory_h=${ac_cv_header_memory_h='yes'}
+ac_cv_header_osreldate_h=${ac_cv_header_osreldate_h='no'}
+ac_cv_header_paths_h=${ac_cv_header_paths_h='yes'}
+ac_cv_header_poll_h=${ac_cv_header_poll_h='yes'}
+ac_cv_header_sys_devpoll_h=${ac_cv_header_sys_devpoll_h='no'}
+ac_cv_header_sys_event_h=${ac_cv_header_sys_event_h='no'}
+ac_cv_header_sys_poll_h=${ac_cv_header_sys_poll_h='yes'}
+ac_cv_header_time=${ac_cv_header_time='yes'}
+ac_cv_header_unistd_h=${ac_cv_header_unistd_h='yes'}
+ac_cv_lbl_gcc_vers=${ac_cv_lbl_gcc_vers='6'}
+ac_cv_lbl_static_flag=${ac_cv_lbl_static_flag='unknown'}
+ac_cv_lib_crypt_crypt=${ac_cv_lib_crypt_crypt='yes'}
+ac_cv_lib_dir_opendir=${ac_cv_lib_dir_opendir='no'}
+ac_cv_lib_inet6_main=${ac_cv_lib_inet6_main='no'}
+ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'}
+ac_cv_prog_CC=${ac_cv_prog_CC='gcc'}
+ac_cv_prog_CPP=${ac_cv_prog_CPP='gcc -E'}
+ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross='no'}
+ac_cv_prog_cc_g=${ac_cv_prog_cc_g='yes'}
+ac_cv_prog_cc_works=${ac_cv_prog_cc_works='yes'}
+ac_cv_prog_gcc=${ac_cv_prog_gcc='yes'}
+ac_cv_prog_make_make_set=${ac_cv_prog_make_make_set='yes'}
--- /dev/null
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2016 Free Software Foundation, Inc.
+
+timestamp='2016-10-02'
+
+# 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 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 <http://www.gnu.org/licenses/>.
+#
+# 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. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+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 <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2016 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 ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # 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 "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { 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 ; set_cc_for_build= ;'
+
+# 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
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
+# 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 tuples: *-*-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=`(uname -p 2>/dev/null || \
+ /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 ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-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) and ABI.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ 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
+ # Determine ABI tags.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ ;;
+ 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/[-_].*//' | cut -d. -f1,2`
+ ;;
+ 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}${abi}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:Sortix:*:*)
+ echo ${UNAME_MACHINE}-unknown-sortix
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # 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 Pn.n version is a patched version.
+ # 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/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ 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 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ 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 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ 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 ;;
+ 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 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ 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 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # 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 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* 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 &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ 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 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????: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 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ 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 ;;
+ *: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 <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ 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 ;;
+ *:AIX:*:[4567])
+ 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/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 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 <stdlib.h>
+ #include <unistd.h>
+
+ 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
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ 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 && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ 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 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ 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 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ 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 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ 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 -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ cris:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ crisv32:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ e2k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ frv:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ hexagon:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ k1om:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #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-${LIBC}"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-${LIBC}
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-${LIBC}
+ exit ;;
+ 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-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-${LIBC}
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
+ riscv32:Linux:*:* | riscv64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ exit ;;
+ x86_64:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ 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 ;;
+ 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 ;;
+ 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 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ 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 ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ 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 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/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 ;;
+ 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 i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ 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 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*: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 | S7501*:*: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; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ 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; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *: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 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ 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 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *: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 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *: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 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite
+config.guess and config.sub with the latest versions from:
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary 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:
--- /dev/null
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+#
+# 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.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# 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 system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+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
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ # 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 alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-cbm-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*: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 ;;
+ 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 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-atari-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-sun-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-apple-openbsd${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 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #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-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ 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 -o $UNAME_PROCESSOR = mc88110 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${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 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ 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:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | 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=4.${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 NetBSD 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/[3478]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
+ 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ 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-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ 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 ;;
+ 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*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ 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/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp3[0-9][05]:OpenBSD:*:*)
+ echo m68k-hp-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo i386-pc-cygwin32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ 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 ;;
+ *:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
+ echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
+ echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
+ echo "powerpc-unknown-linux-gnu" ; exit 0
+ elif test "${UNAME_MACHINE}" = "alpha" ; then
+ echo alpha-unknown-linux-gnu ; exit 0
+ elif test "${UNAME_MACHINE}" = "sparc" ; then
+ echo sparc-unknown-linux-gnu ; exit 0
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us
+ # useful --help. Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ test ! -d /usr/lib/ldscripts/. \
+ && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __ELF__
+ printf ("%s-pc-linux-gnu\n", argv[1]);
+#else
+ printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# 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.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ 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 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*: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.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ 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 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # 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 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ 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
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#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 <sys/param.h>
+ 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`;
+ printf ("%s-next-nextstep%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)
+ printf ("vax-dec-bsd\n"); exit (0);
+#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-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# 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
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
--- /dev/null
+/* config.h - configuration defines for thttpd and libhttpd
+**
+** Copyright © 1995,1998,1999,2000,2001 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+
+/* The following configuration settings are sorted in order of decreasing
+** likelihood that you'd want to change them - most likely first, least
+** likely last.
+**
+** In case you're not familiar with the convention, "#ifdef notdef"
+** is a Berkeleyism used to indicate temporarily disabled code.
+** The idea here is that you re-enable it by just moving it outside
+** of the ifdef.
+*/
+
+/* CONFIGURE: CGI programs must match this pattern to get executed. It's
+** a simple shell-style wildcard pattern, with * meaning any string not
+** containing a slash, ** meaning any string at all, and ? meaning any
+** single character; or multiple such patterns separated by |. The
+** patterns get checked against the filename part of the incoming URL.
+**
+** Restricting CGI programs to a single directory lets the site administrator
+** review them for security holes, and is strongly recommended. If there
+** are individual users that you trust, you can enable their directories too.
+**
+** You can also specify a CGI pattern on the command line, with the -c flag.
+** Such a pattern overrides this compiled-in default.
+**
+** If no CGI pattern is specified, neither here nor on the command line,
+** then CGI programs cannot be run at all. If you want to disable CGI
+** as a security measure that's how you do it, just don't define any
+** pattern here and don't run with the -c flag.
+*/
+#ifdef notdef
+/* Some sample patterns. Allow programs only in one central directory: */
+#define CGI_PATTERN "/cgi-bin/*"
+/* Allow programs in a central directory, or anywhere in a trusted
+** user's tree: */
+#define CGI_PATTERN "/cgi-bin/*|/jef/**"
+/* Allow any program ending with a .cgi: */
+#define CGI_PATTERN "**.cgi"
+/* When virtual hosting, enable the central directory on every host: */
+#define CGI_PATTERN "/*/cgi-bin/*"
+#endif
+
+/* CONFIGURE: How many seconds to allow CGI programs to run before killing
+** them. This is in case someone writes a CGI program that goes into an
+** infinite loop, or does a massive database lookup that would take hours,
+** or whatever. If you don't want any limit, comment this out, but that's
+** probably a really bad idea.
+*/
+#define CGI_TIMELIMIT 30
+
+/* CONFIGURE: Maximum number of simultaneous CGI programs allowed.
+** If this many are already running, then attempts to run more will
+** return an HTTP 503 error. If this is not defined then there's
+** no limit (and you'd better have a lot of memory). This can also be
+** set in the runtime config file.
+*/
+#ifdef notdef
+#define CGI_LIMIT 50
+#endif
+
+/* CONFIGURE: How many seconds to allow for reading the initial request
+** on a new connection.
+*/
+#define IDLE_READ_TIMELIMIT 60
+
+/* CONFIGURE: How many seconds before an idle connection gets closed.
+*/
+#define IDLE_SEND_TIMELIMIT 300
+
+/* CONFIGURE: The syslog facility to use. Using this you can set up your
+** syslog.conf so that all thttpd messages go into a separate file. Note
+** that even if you use the -l command line flag to send logging to a
+** file, errors still get sent via syslog.
+*/
+#define LOG_FACILITY LOG_DAEMON
+
+/* CONFIGURE: Tilde mapping. Many URLs use ~username to indicate a
+** user's home directory. thttpd provides two options for mapping
+** this construct to an actual filename.
+**
+** 1) Map ~username to <prefix>/username. This is the recommended choice.
+** Each user gets a subdirectory in the main chrootable web tree, and
+** the tilde construct points there. The prefix could be something
+** like "users", or it could be empty. See also the makeweb program
+** for letting users create their own web subdirectories.
+**
+** 2) Map ~username to <user's homedir>/<postfix>. The postfix would be
+** the name of a subdirectory off of the user's actual home dir, something
+** like "public_html". This is what Apache and other servers do. The problem
+** is, you can't do this and chroot() at the same time, so it's inherently
+** a security hole. This is strongly dis-recommended, but it's here because
+** some people really want it. Use at your own risk.
+**
+** You can also leave both options undefined, and thttpd will not do
+** anything special about tildes. Enabling both options is an error.
+*/
+#ifdef notdef
+#define TILDE_MAP_1 "users"
+#define TILDE_MAP_2 "public_html"
+#endif
+
+/* CONFIGURE: The file to use for authentication. If this is defined then
+** thttpd checks for this file in the local directory before every fetch.
+** If the file exists then authentication is done, otherwise the fetch
+** proceeds as usual.
+**
+** If you undefine this then thttpd will not implement authentication
+** at all and will not check for auth files, which saves a bit of CPU time.
+*/
+#define AUTH_FILE ".htpasswd"
+
+/* CONFIGURE: The default character set name to use with text MIME types.
+** This gets substituted into the MIME types where they have a "%s".
+**
+** You can override this in the config file with the "charset" setting,
+** or on the command like with the -T flag.
+*/
+#define DEFAULT_CHARSET "UTF-8"
+
+
+/* Most people won't want to change anything below here. */
+
+/* CONFIGURE: This controls the SERVER_NAME environment variable that gets
+** passed to CGI programs. By default thttpd does a gethostname(), which
+** gives the host's canonical name. If you want to always use some other name
+** you can define it here.
+**
+** Alternately, if you want to run the same thttpd binary on multiple
+** machines, and want to build in alternate names for some or all of
+** them, you can define a list of canonical name to altername name
+** mappings. thttpd seatches the list and when it finds a match on
+** the canonical name, that alternate name gets used. If no match
+** is found, the canonical name gets used.
+**
+** If both SERVER_NAME and SERVER_NAME_LIST are defined here, thttpd searches
+** the list as above, and if no match is found then SERVER_NAME gets used.
+**
+** In any case, if thttpd is started with the -h flag, that name always
+** gets used.
+*/
+#ifdef notdef
+#define SERVER_NAME "your.hostname.here"
+#define SERVER_NAME_LIST \
+ "canonical.name.here/alternate.name.here", \
+ "canonical.name.two/alternate.name.two"
+#endif
+
+/* CONFIGURE: Undefine this if you want thttpd to hide its specific version
+** when returning into to browsers. Instead it'll just say "thttpd" with
+** no version.
+*/
+#define SHOW_SERVER_VERSION
+
+/* CONFIGURE: Define this if you want to always chroot(), without having
+** to give the -r command line flag. Some people like this as a security
+** measure, to prevent inadvertant exposure by accidentally running without -r.
+** You can still disable it at runtime with the -nor flag.
+*/
+#ifdef notdef
+#define ALWAYS_CHROOT
+#endif
+
+/* CONFIGURE: Define this if you want to always do virtual hosting, without
+** having to give the -v command line flag. You can still disable it at
+** runtime with the -nov flag.
+*/
+#ifdef notdef
+#define ALWAYS_VHOST
+#endif
+
+/* CONFIGURE: If you're using the vhost feature and you have a LOT of
+** virtual hostnames (like, hundreds or thousands), you will want to
+** enable this feature. It avoids a problem with most Unix filesystems,
+** where if there are a whole lot of items in a directory then name lookup
+** becomes very slow. This feature makes thttpd use subdirectories
+** based on the first characters of each hostname. You can set it to use
+** from one to three characters. If the hostname starts with "www.", that
+** part is skipped over. Dots are also skipped over, and if the name isn't
+** long enough then "_"s are used. Here are some examples of how hostnames
+** would get turned into directory paths, for each different setting:
+** 1: www.acme.com -> a/www.acme.com
+** 1: foobar.acme.com -> f/foobar.acme.com
+** 2: www.acme.com -> a/c/www.acme.com
+** 2: foobar.acme.com -> f/o/foobar.acme.com
+** 3: www.acme.com -> a/c/m/www.acme.com
+** 3: foobar.acme.com -> f/o/o/foobar.acme.com
+** 3: m.tv -> m/t/v/m.tv
+** 4: m.tv -> m/t/v/_/m.tv
+** Note that if you compile this setting in but then forget to set up
+** the corresponding subdirectories, the only error indication you'll
+** get is a "404 Not Found" when you try to visit a site. So be careful.
+*/
+#ifdef notdef
+#define VHOST_DIRLEVELS 1
+#define VHOST_DIRLEVELS 2
+#define VHOST_DIRLEVELS 3
+#endif
+
+/* CONFIGURE: Define this if you want to always use a global passwd file,
+** without having to give the -P command line flag. You can still disable
+** it at runtime with the -noP flag.
+*/
+#ifdef notdef
+#define ALWAYS_GLOBAL_PASSWD
+#endif
+
+/* CONFIGURE: When started as root, the default username to switch to after
+** initializing. If this user (or the one specified by the -u flag) does
+** not exist, the program will refuse to run.
+*/
+#define DEFAULT_USER "nobody"
+
+/* CONFIGURE: When started as root, the program can automatically chdir()
+** to the home directory of the user specified by -u or DEFAULT_USER.
+** An explicit -d still overrides this.
+*/
+#ifdef notdef
+#define USE_USER_DIR
+#endif
+
+/* CONFIGURE: If this is defined, some of the built-in error pages will
+** have more explicit information about exactly what the problem is.
+** Some sysadmins don't like this, for security reasons.
+*/
+#define EXPLICIT_ERROR_PAGES
+
+/* CONFIGURE: Subdirectory for custom error pages. The error filenames are
+** $WEBDIR/$ERR_DIR/err%d.html - if virtual hosting is enabled then
+** $WEBDIR/hostname/$ERR_DIR/err%d.html is searched first. This allows
+** different custom error pages for each virtual hosting web server. If
+** no custom page for a given error can be found, the built-in error page
+** is generated. If ERR_DIR is not defined at all, only the built-in error
+** pages will be generated.
+*/
+#define ERR_DIR "errors"
+
+/* CONFIGURE: Define this if you want a standard HTML tail containing
+** $SERVER_SOFTWARE and $SERVER_ADDRESS to be appended to the custom error
+** pages. (It is always appended to the built-in error pages.)
+*/
+#define ERR_APPEND_SERVER_INFO
+
+/* CONFIGURE: nice(2) value to use for CGI programs. If this is undefined,
+** CGI programs run at normal priority.
+*/
+#define CGI_NICE 10
+
+/* CONFIGURE: $PATH to use for CGI programs.
+*/
+#define CGI_PATH "/usr/local/bin:/usr/ucb:/bin:/usr/bin"
+
+/* CONFIGURE: If defined, $LD_LIBRARY_PATH to use for CGI programs.
+*/
+#ifdef notdef
+#define CGI_LD_LIBRARY_PATH "/usr/local/lib:/usr/lib"
+#endif
+
+/* CONFIGURE: How often to run the occasional cleanup job.
+*/
+#define OCCASIONAL_TIME 120
+
+/* CONFIGURE: Seconds between stats syslogs. If this is undefined then
+** no stats are accumulated and no stats syslogs are done.
+*/
+#define STATS_TIME 3600
+
+/* CONFIGURE: The mmap cache tries to keep the total number of mapped
+** files below this number, so you don't run out of kernel file descriptors.
+** If you have reconfigured your kernel to have more descriptors, you can
+** raise this and thttpd will keep more maps cached. However it's not
+** a hard limit, thttpd will go over it if you really are accessing
+** a whole lot of files.
+*/
+#define DESIRED_MAX_MAPPED_FILES 1000
+
+/* CONFIGURE: The mmap cache also tries to keep the total mapped bytes
+** below this number, so you don't run out of address space. Again
+** it's not a hard limit, thttpd will go over it if you really are
+** accessing a bunch of large files.
+*/
+#define DESIRED_MAX_MAPPED_BYTES 1000000000
+
+
+/* You almost certainly don't want to change anything below here. */
+
+/* CONFIGURE: When throttling CGI programs, we don't know how many bytes
+** they send back to the client because it would be inefficient to
+** interpose a counter. CGI programs are much more expensive than
+** regular files to serve, so we set an arbitrary and high byte count
+** that gets applied to all CGI programs for throttling purposes.
+*/
+#define CGI_BYTECOUNT 25000
+
+/* CONFIGURE: The default port to listen on. 80 is the standard HTTP port.
+*/
+#define DEFAULT_PORT 80
+
+/* CONFIGURE: A list of index filenames to check. The files are searched
+** for in this order.
+*/
+#define INDEX_NAMES "index.html", "index.htm", "index.xhtml", "index.xht", "Default.htm", "index.cgi"
+
+/* CONFIGURE: If this is defined then thttpd will automatically generate
+** index pages for directories that don't have an explicit index file.
+** If you want to disable this behavior site-wide, perhaps for security
+** reasons, just undefine this. Note that you can disable indexing of
+** individual directories by merely doing a "chmod 711" on them - the
+** standard Unix file permission to allow file access but disable "ls".
+*/
+#define GENERATE_INDEXES
+
+/* CONFIGURE: Whether to log unknown request headers. Most sites will not
+** want to log them, which will save them a bit of CPU time.
+*/
+#ifdef notdef
+#define LOG_UNKNOWN_HEADERS
+#endif
+
+/* CONFIGURE: Whether to fflush() the log file after each request. If
+** this is turned off there's a slight savings in CPU cycles.
+*/
+#define FLUSH_LOG_EVERY_TIME
+
+/* CONFIGURE: Time between updates of the throttle table's rolling averages. */
+#define THROTTLE_TIME 2
+
+/* CONFIGURE: The listen() backlog queue length. The 1024 doesn't actually
+** get used, the kernel uses its maximum allowed value. This is a config
+** parameter only in case there's some OS where asking for too high a queue
+** length causes an error. Note that on many systems the maximum length is
+** way too small - see http://www.acme.com/software/thttpd/notes.html
+*/
+#define LISTEN_BACKLOG 1024
+
+/* CONFIGURE: Maximum number of throttle patterns that any single URL can
+** be included in. This has nothing to do with the number of throttle
+** patterns that you can define, which is unlimited.
+*/
+#define MAXTHROTTLENUMS 10
+
+/* CONFIGURE: Number of file descriptors to reserve for uses other than
+** connections. Currently this is 10, representing one for the listen fd,
+** one for dup()ing at connection startup time, one for reading the file,
+** one for syslog, and possibly one for the regular log file, which is
+** five, plus a factor of two for who knows what.
+*/
+#define SPARE_FDS 10
+
+/* CONFIGURE: How many milliseconds to leave a connection open while doing a
+** lingering close.
+*/
+#define LINGER_TIME 500
+
+/* CONFIGURE: Maximum number of symbolic links to follow before
+** assuming there's a loop.
+*/
+#define MAX_LINKS 32
+
+/* CONFIGURE: You don't even want to know.
+*/
+#define MIN_WOULDBLOCK_DELAY 100L
+
+#endif /* _CONFIG_H_ */
--- /dev/null
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+configure:573: checking host system type
+configure:594: checking target system type
+configure:612: checking build system type
+configure:638: checking for gcc
+configure:751: checking whether the C compiler (gcc -g -O2 ) works
+configure:767: gcc -o conftest -g -O2 conftest.c 1>&5
+configure:764:1: warning: return type defaults to 'int' [-Wimplicit-int]
+ main(){return(0);}
+ ^~~~
+configure:793: checking whether the C compiler (gcc -g -O2 ) is a cross-compiler
+configure:798: checking whether we are using GNU C
+configure:807: gcc -E conftest.c
+configure:826: checking whether gcc accepts -g
+configure:861: checking gcc version
+configure:879: checking how to link static binaries
+configure:910: checking for __progname
+configure:923: gcc -o conftest -g -O2 conftest.c 1>&5
+configure: In function 'main':
+configure:919:2: warning: implicit declaration of function 'puts' [-Wimplicit-function-declaration]
+ puts(__progname)
+ ^~~~
+configure:946: checking how to run the C preprocessor
+configure:967: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1029: checking for fcntl.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1029: checking for grp.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1029: checking for memory.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1029: checking for paths.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1029: checking for poll.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1029: checking for sys/poll.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1029: checking for sys/devpoll.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1035:25: fatal error: sys/devpoll.h: No such file or directory
+ #include <$ac_hdr>
+ ^
+compilation terminated.
+configure: failed program was:
+#line 1034 "configure"
+#include "confdefs.h"
+#include <sys/devpoll.h>
+configure:1029: checking for sys/event.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1035:23: fatal error: sys/event.h: No such file or directory
+ #include <$ac_hdr>
+ ^
+compilation terminated.
+configure: failed program was:
+#line 1034 "configure"
+#include "confdefs.h"
+#include <sys/event.h>
+configure:1029: checking for osreldate.h
+configure:1039: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1035:23: fatal error: osreldate.h: No such file or directory
+ #include <$ac_hdr>
+ ^
+compilation terminated.
+configure: failed program was:
+#line 1034 "configure"
+#include "confdefs.h"
+#include <osreldate.h>
+configure:1066: checking whether time.h and sys/time.h may both be included
+configure:1080: gcc -c -g -O2 conftest.c 1>&5
+configure:1105: checking for dirent.h that defines DIR
+configure:1118: gcc -c -g -O2 conftest.c 1>&5
+configure:1143: checking for opendir in -ldir
+configure:1162: gcc -o conftest -g -O2 conftest.c -ldir 1>&5
+/usr/bin/ld: cannot find -ldir
+collect2: error: ld returned 1 exit status
+configure: failed program was:
+#line 1151 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+configure:1228: checking for /usr/local/v6/lib
+configure:1238: checking for gethostbyname
+configure:1266: gcc -o conftest -g -O2 conftest.c 1>&5
+configure:1451: checking for socket
+configure:1479: gcc -o conftest -g -O2 conftest.c 1>&5
+configure:1580: checking for main in -linet6
+configure:1595: gcc -o conftest -g -O2 conftest.c -linet6 1>&5
+/usr/bin/ld: cannot find -linet6
+collect2: error: ld returned 1 exit status
+configure: failed program was:
+#line 1588 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+configure:1624: checking for crypt
+configure:1652: gcc -o conftest -g -O2 conftest.c 1>&5
+/tmp/cc83IuJy.o: In function `main':
+/home/ralph/src/thttpd/thttpd-2.29/configure:1646: undefined reference to `crypt'
+collect2: error: ld returned 1 exit status
+configure: failed program was:
+#line 1629 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char crypt(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char crypt();
+
+int main() {
+
+/* 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_crypt) || defined (__stub___crypt)
+choke me
+#else
+crypt();
+#endif
+
+; return 0; }
+configure:1670: checking for crypt in -lcrypt
+configure:1689: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1719: checking for hstrerror
+configure:1747: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1810: checking for strerror
+configure:1838: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for waitpid
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for vsnprintf
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1879:6: warning: conflicting types for built-in function 'vsnprintf'
+ char $ac_func();
+ ^~~~~~~~~
+configure:1867: checking for daemon
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for setsid
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for setlogin
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure: In function 'main':
+configure:1887:1: error: unknown type name 'choke'
+ choke me
+ ^~~~~
+configure: failed program was:
+#line 1872 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char setlogin(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char setlogin();
+
+int main() {
+
+/* 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_setlogin) || defined (__stub___setlogin)
+choke me
+#else
+setlogin();
+#endif
+
+; return 0; }
+configure:1867: checking for getaddrinfo
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for getnameinfo
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for gai_strerror
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for kqueue
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+/tmp/cccBW2WQ.o: In function `main':
+/home/ralph/src/thttpd/thttpd-2.29/configure:1889: undefined reference to `kqueue'
+collect2: error: ld returned 1 exit status
+configure: failed program was:
+#line 1872 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char kqueue(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char kqueue();
+
+int main() {
+
+/* 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_kqueue) || defined (__stub___kqueue)
+choke me
+#else
+kqueue();
+#endif
+
+; return 0; }
+configure:1867: checking for sigset
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1867: checking for atoll
+configure:1895: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:1923: checking for unistd.h
+configure:1933: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1962: checking for getpagesize
+configure:1990: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:2015: checking for working mmap
+configure:2163: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:2094:7: warning: conflicting types for built-in function 'malloc'
+ char *malloc();
+ ^~~~~~
+configure: In function 'main':
+configure:2104:13: warning: implicit declaration of function 'getpagesize' [-Wimplicit-function-declaration]
+ pagesize = getpagesize();
+ ^~~~~~~~~~~
+configure:2111:3: warning: implicit declaration of function 'exit' [-Wimplicit-function-declaration]
+ exit(1);
+ ^~~~
+configure:2111:3: warning: incompatible implicit declaration of built-in function 'exit'
+configure:2111:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2113:17: warning: implicit declaration of function 'rand' [-Wimplicit-function-declaration]
+ *(data + i) = rand();
+ ^~~~
+configure:2114:2: warning: implicit declaration of function 'umask' [-Wimplicit-function-declaration]
+ umask(0);
+ ^~~~~
+configure:2117:3: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2117:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2118:6: warning: implicit declaration of function 'write' [-Wimplicit-function-declaration]
+ if (write(fd, data, pagesize) != pagesize)
+ ^~~~~
+configure:2119:3: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2119:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2120:2: warning: implicit declaration of function 'close' [-Wimplicit-function-declaration]
+ close(fd);
+ ^~~~~
+configure:2129:3: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2129:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2132:3: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2132:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2133:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ ^
+configure:2136:3: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2136:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2139:4: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2139:4: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2150:3: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2150:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2151:6: warning: implicit declaration of function 'read' [-Wimplicit-function-declaration]
+ if (read(fd, data3, pagesize) != pagesize)
+ ^~~~
+configure:2152:3: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2152:3: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2155:4: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(1);
+ ^~~~
+configure:2155:4: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2157:2: warning: implicit declaration of function 'unlink' [-Wimplicit-function-declaration]
+ unlink("conftestmmap");
+ ^~~~~~
+configure:2158:2: warning: incompatible implicit declaration of built-in function 'exit'
+ exit(0);
+ ^~~~
+configure:2158:2: note: include '<stdlib.h>' or provide a declaration of 'exit'
+configure:2248: checking for select
+configure:2276: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:2248: checking for poll
+configure:2276: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5
+configure:2304: checking if struct tm has tm_gmtoff member
+configure:2318: gcc -c -g -O2 conftest.c 1>&5
+configure:2338: checking if int64_t exists
+configure:2351: gcc -c -g -O2 conftest.c 1>&5
+configure:2371: checking if socklen_t exists
+configure:2385: gcc -c -g -O2 conftest.c 1>&5
+configure:2406: checking whether make sets ${MAKE}
+configure:2444: checking for a BSD compatible install
--- /dev/null
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host stolpe:
+#
+# ./configure --build=x86_64-linux-gnu --prefix=/usr '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules '--libdir=${prefix}/lib/x86_64-linux-gnu' '--libexecdir=${prefix}/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr/local --mandir=/usr/local/man
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: ./config.status [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running ${CONFIG_SHELL-/bin/sh} ./configure --build=x86_64-linux-gnu --prefix=/usr '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules '--libdir=${prefix}/lib/x86_64-linux-gnu' '--libexecdir=${prefix}/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr/local --mandir=/usr/local/man --no-create --no-recursion"
+ exec ${CONFIG_SHELL-/bin/sh} ./configure --build=x86_64-linux-gnu --prefix=/usr '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules '--libdir=${prefix}/lib/x86_64-linux-gnu' '--libexecdir=${prefix}/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr/local --mandir=/usr/local/man --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "./config.status generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "$ac_cs_usage"; exit 0 ;;
+ *) echo "$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=.
+ac_given_INSTALL="/usr/bin/install -c"
+
+trap 'rm -fr Makefile cgi-src/Makefile extras/Makefile conftest*; exit 1' 1 2 15
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\&%]/\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
+/^[ ]*VPATH[ ]*=[^:]*$/d
+
+s%@SHELL@%/bin/sh%g
+s%@CFLAGS@%-g -O2%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%-g -O2%g
+s%@FFLAGS@%-g -O2%g
+s%@DEFS@% -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1 %g
+s%@LDFLAGS@%%g
+s%@LIBS@%-lcrypt %g
+s%@exec_prefix@%${prefix}%g
+s%@prefix@%/usr/local%g
+s%@program_transform_name@%s,x,x,%g
+s%@bindir@%${exec_prefix}/bin%g
+s%@sbindir@%${exec_prefix}/sbin%g
+s%@libexecdir@%${prefix}/lib/x86_64-linux-gnu%g
+s%@datadir@%${prefix}/share%g
+s%@sysconfdir@%/etc%g
+s%@sharedstatedir@%${prefix}/com%g
+s%@localstatedir@%/var%g
+s%@libdir@%${prefix}/lib/x86_64-linux-gnu%g
+s%@includedir@%${prefix}/include%g
+s%@oldincludedir@%/usr/include%g
+s%@infodir@%${prefix}/share/info%g
+s%@mandir@%/usr/local/man%g
+s%@host@%x86_64-pc-linux-gnu%g
+s%@host_alias@%x86_64-pc-linux-gnu%g
+s%@host_cpu@%x86_64%g
+s%@host_vendor@%pc%g
+s%@host_os@%linux-gnu%g
+s%@target@%x86_64-pc-linux-gnu%g
+s%@target_alias@%x86_64-pc-linux-gnu%g
+s%@target_cpu@%x86_64%g
+s%@target_vendor@%pc%g
+s%@target_os@%linux-gnu%g
+s%@build@%x86_64-pc-linux-gnu%g
+s%@build_alias@%x86_64-linux-gnu%g
+s%@build_cpu@%x86_64%g
+s%@build_vendor@%pc%g
+s%@build_os@%linux-gnu%g
+s%@CC@%gcc%g
+s%@CPP@%gcc -E%g
+s%@LIBOBJS@%%g
+s%@SET_MAKE@%%g
+s%@INSTALL_PROGRAM@%${INSTALL}%g
+s%@INSTALL_SCRIPT@%${INSTALL_PROGRAM}%g
+s%@INSTALL_DATA@%${INSTALL} -m 644%g
+s%@V_CCOPT@%-O2%g
+s%@V_STATICFLAG@%%g
+s%@V_NETLIBS@%%g
+
+CEOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+
+CONFIG_FILES=${CONFIG_FILES-"Makefile cgi-src/Makefile extras/Makefile"}
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+
+
+exit 0
--- /dev/null
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2016 Free Software Foundation, Inc.
+
+timestamp='2016-11-04'
+
+# 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 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 <http://www.gnu.org/licenses/>.
+#
+# 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. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# 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.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# 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 or 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 <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2016 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 ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # 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 ;;
+
+ * )
+ 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* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+ kopensolaris*-gnu* | cloudabi*-eabi* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
+ *)
+ 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 | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -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
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -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/'`
+ ;;
+ -sco5v6*)
+ # 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*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
+ -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 \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | ba \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pru \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | we32k \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # 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-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | ba-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | e2k-* | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pru-* \
+ | pyramid-* \
+ | riscv32-* | riscv64-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # 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
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ 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
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ 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
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ 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
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ 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
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
+ 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*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
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ 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
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
+ 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
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ 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
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-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-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle)
+ 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)
+ 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
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ 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
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ 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
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ 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
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ 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
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-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
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ 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
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ 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.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -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* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -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* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos* | -phoenix* | -fuchsia*)
+ # 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* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -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
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -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
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -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
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
+ -ios)
+ ;;
+ -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
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
+ ;;
+ # 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
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ 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
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-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
+ ;;
+ -cnk*|-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
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -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
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+# 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.
+
+# 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.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+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
+ linux-gnu*)
+ 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)
+ os=
+ 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/'`
+ ;;
+ -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
+ ;;
+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.
+ tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
+ | arme[lb] | pyramid \
+ | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
+ | alpha | we32k | ns16k | clipper | i370 | sh \
+ | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
+ | pdp11 | mips64el | mips64orion | mips64orionel \
+ | sparc | sparclet | sparclite | sparc64)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # 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[3456]86)
+ 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.
+ vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+ | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
+ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
+ | hppa-* | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
+ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
+ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* | f301-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigados)
+ basic_machine=m68k-cbm
+ os=-amigados
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ 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 | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ 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
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-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
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[3456]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i[3456]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i[3456]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i[3456]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ 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
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ 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)
+ basic_machine=i586-intel
+ ;;
+ pentiumpro | p6)
+ basic_machine=i686-intel
+ ;;
+ pentium-* | p5-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-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/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ 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
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ 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
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ 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.
+ mips)
+ basic_machine=mips-mips
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ *)
+ 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
+ ;;
+ -unixware* | svr4*)
+ os=-sysv4
+ ;;
+ -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* \
+ | -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* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -linux-gnu* | -uxpv*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -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|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ # 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*)
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -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*-semi)
+ os=-aout
+ ;;
+ 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
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigados
+ ;;
+ *-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
+ ;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
+ *)
+ 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
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
--- /dev/null
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -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 ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$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" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$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)
+ # 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 << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$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" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ 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)
+ 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" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -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 ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=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" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=thttpd.c
+
+# 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 its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ 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
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+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
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:638: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+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
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:668: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_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 $# -gt 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
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:719: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:751: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 762 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:767: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:793: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:798: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:807: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:826: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&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
+
+
+V_CCOPT="-O"
+if test "$GCC" = yes ; then
+ echo $ac_n "checking gcc version""... $ac_c" 1>&6
+echo "configure:861: checking gcc version" >&5
+ if eval "test \"`echo '$''{'ac_cv_lbl_gcc_vers'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_lbl_gcc_vers=`$CC -dumpversion 2>&1 | \
+ sed -e 's/\..*//'`
+fi
+
+ echo "$ac_t""$ac_cv_lbl_gcc_vers" 1>&6
+ if test "$ac_cv_lbl_gcc_vers" -gt 1 ; then
+ V_CCOPT="-O2"
+ fi
+fi
+if test -f .devel ; then
+ V_CCOPT="-g $V_CCOPT -ansi -pedantic -U__STRICT_ANSI__ -Wall -Wpointer-arith -Wshadow -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wno-long-long"
+fi
+
+echo $ac_n "checking how to link static binaries""... $ac_c" 1>&6
+echo "configure:879: checking how to link static binaries" >&5
+if eval "test \"`echo '$''{'ac_cv_lbl_static_flag'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_lbl_static_flag=unknown
+ echo 'main() {}' > conftest.c
+ if test "$GCC" != yes ; then
+ trial_flag="-Bstatic"
+ test=`$CC $trial_flag -o conftest conftest.c 2>&1`
+ if test -z "$test" ; then
+ ac_cv_lbl_static_flag="$trial_flag"
+ fi
+ rm -f conftest
+ fi
+ if test "$ac_cv_lbl_static_flag" = unknown ; then
+ trial_flag="-static"
+ test=`$CC $trial_flag -o conftest conftest.c 2>&1`
+ if test -z "$test" ; then
+ ac_cv_lbl_static_flag="$trial_flag"
+ fi
+ rm -f conftest
+ fi
+ rm conftest.c
+fi
+
+echo "$ac_t""$ac_cv_lbl_static_flag" 1>&6
+if test "$ac_cv_lbl_static_flag" != unknown ; then
+ V_STATICFLAG="$ac_cv_lbl_static_flag"
+fi
+
+echo $ac_n "checking for __progname""... $ac_c" 1>&6
+echo "configure:910: checking for __progname" >&5
+if eval "test \"`echo '$''{'ac_cv_extern__progname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 915 "configure"
+#include "confdefs.h"
+
+int main() {
+extern char *__progname;
+ puts(__progname)
+; return 0; }
+EOF
+if { (eval echo configure:923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_extern__progname=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_extern__progname=no
+fi
+rm -f conftest*
+fi
+
+if test $ac_cv_extern__progname = yes ; then
+ cat >> confdefs.h <<\EOF
+#define HAVE__PROGNAME 1
+EOF
+
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:946: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 961 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:967: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 978 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:984: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 995 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1001: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/devpoll.h sys/event.h osreldate.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1029: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1034 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1039: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:1066: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1071 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:1080: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:1105: checking for $ac_hdr that defines DIR" >&5
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1110 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:1118: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:1143: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldir $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1151 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ldir"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:1184: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lx $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1192 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lx"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+d="/usr/local/v6/lib"
+echo $ac_n "checking for $d""... $ac_c" 1>&6
+echo "configure:1228: checking for $d" >&5
+if test -d $d; then
+ echo "$ac_t""yes (Adding -L$d to LDFLAGS)" 1>&6
+ LDFLAGS="$LDFLAGS -L$d"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+V_NETLIBS=""
+echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
+echo "configure:1238: checking for gethostbyname" >&5
+if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1243 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gethostbyname(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+
+/* 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_gethostbyname) || defined (__stub___gethostbyname)
+choke me
+#else
+gethostbyname();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1266: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+# Some OSes (eg. Solaris) place it in libnsl:
+ echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:1285: checking for gethostbyname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyname'_' | sed 'y%./+- %__p__%'`
+if eval "test \"`echo '$''{'ac_cv_lbl_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1293 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:1304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ V_NETLIBS="-lnsl $V_NETLIBS"
+else
+ echo "$ac_t""no" 1>&6
+# Some strange OSes (SINIX) have it in libsocket:
+ echo $ac_n "checking for gethostbyname in -lsocket""... $ac_c" 1>&6
+echo "configure:1324: checking for gethostbyname in -lsocket" >&5
+ac_lib_var=`echo socket'_'gethostbyname'_' | sed 'y%./+- %__p__%'`
+if eval "test \"`echo '$''{'ac_cv_lbl_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1332 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:1343: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ V_NETLIBS="-lsocket $V_NETLIBS"
+else
+ echo "$ac_t""no" 1>&6
+# Unfortunately libsocket sometimes depends on libnsl.
+ # AC_CHECK_LIB's API is essentially broken so the
+ # following ugliness is necessary:
+ echo $ac_n "checking for gethostbyname in -lsocket""... $ac_c" 1>&6
+echo "configure:1365: checking for gethostbyname in -lsocket" >&5
+ac_lib_var=`echo socket'_'gethostbyname'_'-lnsl | sed 'y%./+- %__p__%'`
+if eval "test \"`echo '$''{'ac_cv_lbl_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket -lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1373 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:1384: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ V_NETLIBS="-lsocket -lnsl $V_NETLIBS"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for gethostbyname in -lresolv""... $ac_c" 1>&6
+echo "configure:1403: checking for gethostbyname in -lresolv" >&5
+ac_lib_var=`echo resolv'_'gethostbyname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1411 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:1422: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ V_NETLIBS="-lresolv $V_NETLIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+fi
+
+fi
+
+fi
+
+echo $ac_n "checking for socket""... $ac_c" 1>&6
+echo "configure:1451: checking for socket" >&5
+if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1456 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char socket(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+
+/* 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_socket) || defined (__stub___socket)
+choke me
+#else
+socket();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_socket=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_socket=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:1497: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1505 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1516: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ V_NETLIBS="-lsocket $V_NETLIBS"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:1535: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket'_'-lnsl | sed 'y%./+- %__p__%'`
+if eval "test \"`echo '$''{'ac_cv_lbl_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket -lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1543 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lbl_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ V_NETLIBS="-lsocket -lnsl $V_NETLIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+fi
+
+
+echo $ac_n "checking for main in -linet6""... $ac_c" 1>&6
+echo "configure:1580: checking for main in -linet6" >&5
+ac_lib_var=`echo inet6'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-linet6 $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1588 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1595: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo inet6 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-linet6 $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for crypt""... $ac_c" 1>&6
+echo "configure:1624: checking for crypt" >&5
+if eval "test \"`echo '$''{'ac_cv_func_crypt'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1629 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char crypt(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char crypt();
+
+int main() {
+
+/* 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_crypt) || defined (__stub___crypt)
+choke me
+#else
+crypt();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_crypt=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_crypt=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'crypt`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
+echo "configure:1670: checking for crypt in -lcrypt" >&5
+ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcrypt $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1678 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char crypt();
+
+int main() {
+crypt()
+; return 0; }
+EOF
+if { (eval echo configure:1689: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo crypt | sed -e 's/^a-zA-Z0-9_/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lcrypt $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking for hstrerror""... $ac_c" 1>&6
+echo "configure:1719: checking for hstrerror" >&5
+if eval "test \"`echo '$''{'ac_cv_func_hstrerror'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1724 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char hstrerror(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char hstrerror();
+
+int main() {
+
+/* 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_hstrerror) || defined (__stub___hstrerror)
+choke me
+#else
+hstrerror();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_hstrerror=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_hstrerror=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'hstrerror`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for hstrerror in -lresolv""... $ac_c" 1>&6
+echo "configure:1765: checking for hstrerror in -lresolv" >&5
+ac_lib_var=`echo resolv'_'hstrerror | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1773 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char hstrerror();
+
+int main() {
+hstrerror()
+; return 0; }
+EOF
+if { (eval echo configure:1784: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ V_NETLIBS="-lresolv $V_NETLIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+for ac_func in strerror
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1810: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1815 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"
+fi
+done
+
+
+for ac_func in waitpid vsnprintf daemon setsid setlogin getaddrinfo getnameinfo gai_strerror kqueue sigset atoll
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1867: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1872 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1923: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1928 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1933: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1962: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1967 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:2015: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2023 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize();
+
+ /*
+ * First, make a file with some known garbage in it.
+ */
+ data = malloc(pagesize);
+ if (!data)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand();
+ umask(0);
+ fd = creat("conftestmmap", 0600);
+ if (fd < 0)
+ exit(1);
+ if (write(fd, data, pagesize) != pagesize)
+ exit(1);
+ close(fd);
+
+ /*
+ * Next, try to mmap the file at a fixed address which
+ * already has something else allocated at it. If we can,
+ * also make sure that we see the same garbage.
+ */
+ fd = open("conftestmmap", O_RDWR);
+ if (fd < 0)
+ exit(1);
+ data2 = malloc(2 * pagesize);
+ if (!data2)
+ exit(1);
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit(1);
+
+ /*
+ * Finally, make sure that changes to the mapped area
+ * do not percolate back to the file as seen by read().
+ * (This is a bug on some variants of i386 svr4.0.)
+ */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = malloc(pagesize);
+ if (!data3)
+ exit(1);
+ if (read(fd, data3, pagesize) != pagesize)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit(1);
+ close(fd);
+ unlink("conftestmmap");
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:2163: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+
+case "$target_os" in
+solaris*)
+ for ac_func in poll
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2191: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2196 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2219: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ ;;
+*)
+ for ac_func in select poll
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2248: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2253 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ ;;
+esac
+
+echo $ac_n "checking if struct tm has tm_gmtoff member""... $ac_c" 1>&6
+echo "configure:2304: checking if struct tm has tm_gmtoff member" >&5
+ if eval "test \"`echo '$''{'ac_cv_acme_tm_has_tm_gmtoff'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2309 "configure"
+#include "confdefs.h"
+
+# include <sys/types.h>
+# include <time.h>
+int main() {
+u_int i = sizeof(((struct tm *)0)->tm_gmtoff)
+; return 0; }
+EOF
+if { (eval echo configure:2318: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_acme_tm_has_tm_gmtoff=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_acme_tm_has_tm_gmtoff=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$ac_cv_acme_tm_has_tm_gmtoff" 1>&6
+ if test $ac_cv_acme_tm_has_tm_gmtoff = yes ; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_TM_GMTOFF 1
+EOF
+
+ fi
+echo $ac_n "checking if int64_t exists""... $ac_c" 1>&6
+echo "configure:2338: checking if int64_t exists" >&5
+ if eval "test \"`echo '$''{'ac_cv_acme_int64_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2343 "configure"
+#include "confdefs.h"
+
+# include <sys/types.h>
+int main() {
+int64_t i64
+; return 0; }
+EOF
+if { (eval echo configure:2351: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_acme_int64_t=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_acme_int64_t=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$ac_cv_acme_int64_t" 1>&6
+ if test $ac_cv_acme_int64_t = yes ; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_INT64T 1
+EOF
+
+ fi
+echo $ac_n "checking if socklen_t exists""... $ac_c" 1>&6
+echo "configure:2371: checking if socklen_t exists" >&5
+ if eval "test \"`echo '$''{'ac_cv_acme_socklen_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2376 "configure"
+#include "confdefs.h"
+
+# include <sys/types.h>
+# include <sys/socket.h>
+int main() {
+socklen_t slen
+; return 0; }
+EOF
+if { (eval echo configure:2385: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_acme_socklen_t=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_acme_socklen_t=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$ac_cv_acme_socklen_t" 1>&6
+ if test $ac_cv_acme_socklen_t = yes ; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SOCKLENT 1
+EOF
+
+ fi
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:2406: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# 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
+# 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"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:2444: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/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
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+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. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&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_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# 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. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# 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.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile cgi-src/Makefile extras/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@V_CCOPT@%$V_CCOPT%g
+s%@V_STATICFLAG@%$V_STATICFLAG%g
+s%@V_NETLIBS@%$V_NETLIBS%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile cgi-src/Makefile extras/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
--- /dev/null
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(thttpd.c)
+
+AC_CANONICAL_SYSTEM
+
+AC_PROG_CC
+
+V_CCOPT="-O"
+if test "$GCC" = yes ; then
+ AC_MSG_CHECKING(gcc version)
+ AC_CACHE_VAL(ac_cv_lbl_gcc_vers,
+ ac_cv_lbl_gcc_vers=`$CC -dumpversion 2>&1 | \
+ sed -e 's/\..*//'`)
+ AC_MSG_RESULT($ac_cv_lbl_gcc_vers)
+ if test "$ac_cv_lbl_gcc_vers" -gt 1 ; then
+ V_CCOPT="-O2"
+ fi
+fi
+if test -f .devel ; then
+ V_CCOPT="-g $V_CCOPT -ansi -pedantic -U__STRICT_ANSI__ -Wall -Wpointer-arith -Wshadow -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wno-long-long"
+fi
+
+dnl
+dnl maybe this should be a loop
+dnl
+AC_MSG_CHECKING(how to link static binaries)
+AC_CACHE_VAL(ac_cv_lbl_static_flag,
+ ac_cv_lbl_static_flag=unknown
+ echo 'main() {}' > conftest.c
+ if test "$GCC" != yes ; then
+ trial_flag="-Bstatic"
+ test=`$CC $trial_flag -o conftest conftest.c 2>&1`
+ if test -z "$test" ; then
+ ac_cv_lbl_static_flag="$trial_flag"
+ fi
+ rm -f conftest
+ fi
+ if test "$ac_cv_lbl_static_flag" = unknown ; then
+ trial_flag="-static"
+ test=`$CC $trial_flag -o conftest conftest.c 2>&1`
+ if test -z "$test" ; then
+ ac_cv_lbl_static_flag="$trial_flag"
+ fi
+ rm -f conftest
+ fi
+ rm conftest.c)
+AC_MSG_RESULT($ac_cv_lbl_static_flag)
+if test "$ac_cv_lbl_static_flag" != unknown ; then
+ V_STATICFLAG="$ac_cv_lbl_static_flag"
+fi
+
+AC_MSG_CHECKING(for __progname)
+AC_CACHE_VAL(ac_cv_extern__progname,
+ AC_TRY_LINK([],
+ [extern char *__progname;
+ puts(__progname)],
+ ac_cv_extern__progname=yes,
+ ac_cv_extern__progname=no))
+if test $ac_cv_extern__progname = yes ; then
+ AC_DEFINE(HAVE__PROGNAME)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_CHECK_HEADERS(fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/devpoll.h sys/event.h osreldate.h)
+AC_HEADER_TIME
+AC_HEADER_DIRENT
+
+d="/usr/local/v6/lib"
+AC_MSG_CHECKING(for $d)
+if test -d $d; then
+ AC_MSG_RESULT(yes (Adding -L$d to LDFLAGS))
+ LDFLAGS="$LDFLAGS -L$d"
+else
+ AC_MSG_RESULT(no)
+fi
+
+dnl
+dnl Most operating systems have gethostbyname() in the default searched
+dnl libraries (i.e. libc):
+dnl
+V_NETLIBS=""
+AC_CHECK_FUNC(gethostbyname, ,
+ # Some OSes (eg. Solaris) place it in libnsl:
+ AC_LBL_CHECK_LIB(nsl, gethostbyname,
+ V_NETLIBS="-lnsl $V_NETLIBS",
+ # Some strange OSes (SINIX) have it in libsocket:
+ AC_LBL_CHECK_LIB(socket, gethostbyname,
+ V_NETLIBS="-lsocket $V_NETLIBS",
+ # Unfortunately libsocket sometimes depends on libnsl.
+ # AC_CHECK_LIB's API is essentially broken so the
+ # following ugliness is necessary:
+ AC_LBL_CHECK_LIB(socket, gethostbyname,
+ V_NETLIBS="-lsocket -lnsl $V_NETLIBS",
+ AC_CHECK_LIB(resolv, gethostbyname,
+ V_NETLIBS="-lresolv $V_NETLIBS"),
+ -lnsl))))
+AC_CHECK_FUNC(socket, ,
+ AC_CHECK_LIB(socket, socket,
+ V_NETLIBS="-lsocket $V_NETLIBS",
+ AC_LBL_CHECK_LIB(socket, socket,
+ V_NETLIBS="-lsocket -lnsl $V_NETLIBS", , -lnsl)))
+
+AC_CHECK_LIB(inet6, main)
+
+AC_CHECK_FUNC(crypt, , AC_CHECK_LIB(crypt, crypt))
+AC_CHECK_FUNC(hstrerror, ,
+ AC_CHECK_LIB(resolv, hstrerror, V_NETLIBS="-lresolv $V_NETLIBS"))
+
+AC_REPLACE_FUNCS(strerror)
+AC_CHECK_FUNCS(waitpid vsnprintf daemon setsid setlogin getaddrinfo getnameinfo gai_strerror kqueue sigset atoll)
+AC_FUNC_MMAP
+
+case "$target_os" in
+solaris*)
+ dnl Solaris's select() is a bad wrapper routine.
+ AC_CHECK_FUNCS(poll)
+ ;;
+*)
+ AC_CHECK_FUNCS(select poll)
+ ;;
+esac
+
+AC_ACME_TM_GMTOFF
+AC_ACME_INT64T
+AC_ACME_SOCKLENT
+
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+
+AC_SUBST(DEFS)
+AC_SUBST(V_CCOPT)
+AC_SUBST(V_STATICFLAG)
+AC_SUBST(V_NETLIBS)
+
+AC_OUTPUT(Makefile cgi-src/Makefile extras/Makefile)
--- /dev/null
+# This section overrides defaults
+dir=/home/httpd/html
+chroot
+user=httpd# default = nobody
+logfile=/var/log/thttpd.log
+pidfile=/var/run/thttpd.pid
+# This section _documents_ defaults in effect
+# port=80
+# nosymlink# default = !chroot
+# novhost
+# nocgipat
+# nothrottles
+# host=0.0.0.0
+# charset=iso-8859-1
--- /dev/null
+#!/bin/bash
+# The following two lines enable chkconfig(1) to manipulate this script
+# chkconfig: 2345 99 01
+# description: control Jef Poskanzer's tiny/turbo/throttling http daemon
+
+# source function library
+. /etc/rc.d/init.d/functions
+
+pidfile=/var/run/thttpd.pid
+pid=`cat $pidfile 2>/dev/null`
+
+if test -n "$pid" && kill -0 $pid 2>/dev/null; then
+ dead=no
+else
+ dead=yes
+fi
+
+die(){
+ echo -n "$*"; echo_failure; echo ''
+ exit 1;
+}
+
+case "$1" in
+ start) test "$dead" = yes || die thttpd is already running
+ echo -n "Starting thttpd: "
+ daemon /usr/sbin/thttpd -C /etc/thttpd.conf
+ touch /var/lock/subsys/thttpd
+ echo_success;echo ''
+ exit 0
+ ;;
+ stop) echo -n "Gently shutting down thttpd: "
+ signal=USR1
+ ;;
+ kill) echo -n "Violently killing thttpd: "
+ signal=INT
+ ;;
+status) status thttpd; exit $?;;
+restart) $0 stop; sleep 2; exec $0 start;;
+ *) die "Usage: thttpd {start|stop|restart|status}";;
+esac
+
+test "$dead" = no || die thttpd is not running
+kill -$signal $pid
+sleep 2
+kill -0 $pid 2>/dev/null && die "thttpd[$pid] will not die"
+rm -f /var/lock/subsys/thttpd
+echo_success; echo ''
--- /dev/null
+Summary: Throttleable lightweight httpd server
+Name: thttpd
+Version: 2.29
+Release: 1
+Group: Networking
+URL: http://www.acme.com/software/thttpd
+Source0: http://www.acme.com/software/thttpd/thttpd-%{PACKAGE_VERSION}.tar.gz
+Copyright: distributable (BSD)
+BuildRoot: /tmp/thttpd-root
+
+%description
+Thttpd is a very compact no-frills httpd serving daemon that can handle
+very high loads. While lacking many of the advanced features of
+Apachee, thttpd operates without forking and is extremely efficient in
+memory use. Basic support for cgi scripts, authentication, and ssi is
+provided for. Advanced features include the ability to throttle traffic.
+
+%prep
+%setup
+
+./configure --prefix=/usr
+
+%build
+make \
+ WEBDIR=/home/httpd/html \
+ BINDIR=/usr/sbin prefix=/usr \
+ CGIBINDIR=/home/httpd/cgi-bin
+
+%install
+
+mkdir -p $RPM_BUILD_ROOT/home/httpd/{cgi-bin,logs}
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+mkdir -p $RPM_BUILD_ROOT/usr/man/man{1,8}
+mkdir -p $RPM_BUILD_ROOT/usr/sbin
+install contrib/redhat-rpm/thttpd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/thttpd
+install contrib/redhat-rpm/thttpd.conf $RPM_BUILD_ROOT/etc/
+make -i prefix=$RPM_BUILD_ROOT/usr install
+
+%pre
+
+grep '^httpd:' /etc/passwd >/dev/null || \
+ /usr/sbin/adduser -r httpd
+
+%post
+/sbin/chkconfig --add thttpd
+
+%preun
+/sbin/chkconfig --del thttpd
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,bin,bin)
+%doc [A-Z]*
+%attr(2755, httpd, httpd) /usr/sbin/makeweb
+/usr/sbin/htpasswd
+/usr/sbin/syslogtocern
+/usr/sbin/thttpd
+%attr(-, httpd, httpd) /home/httpd
+%attr(0755, root, root) /etc/rc.d/init.d/thttpd
+%config /etc/thttpd.conf
+%doc /usr/man/man*/*
+
+%changelog
+
+* Mon Dec 29 2003 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.26
+
+* Sat Dec 20 2003 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.25b
+
+* Mon Oct 27 2003 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.25
+
+* Sat Sep 13 2003 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.24
+
+* Sat May 25 2002 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.23
+
+* Mon Jul 09 2001 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.22
+
+* Thu Apr 26 2001 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.21c
+
+* Mon Apr 23 2001 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.21b
+
+* Mon Oct 02 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.21
+
+* Wed Sep 13 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.20
+
+* Mon Sep 11 2000 Bennett Todd <bet@rahul.net>
+ - added thttpd.conf, took config info out of init script
+ - switched to logging in /var/log, used pidfile
+
+* Thu Jun 15 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.19
+
+* Thu May 18 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.18
+
+* Fri Mar 17 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.17
+
+* Mon Feb 28 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.16
+
+* Thu Feb 03 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.15
+
+* Thu Jan 21 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.14
+
+* Thu Jan 6 2000 Jef Poskanzer <jef@mail.acme.com>
+ - Updated to 2.13
+
+* Mon Jan 3 2000 Bennett Todd <bet@rahul.net>
+ - updated to 2.12, tweaked to move thttpd.init into tarball
+
+* Mon Dec 13 1999 Bennett Todd <bet@mordor.net>
+ - Updated to 2.09
+
+* Fri Dec 10 1999 Bennett Todd <bet@mordor.net>
+ - Updated to 2.08
+
+* Wed Nov 24 1999 Bennett Todd <bet@mordor.net>
+ - updated to 2.06, parameterized Version string in source url
+ - changed to use "make install", simplified %files list
+
+* Wed Nov 10 1999 Bennett Todd <bet@mordor.net>
+ - Version 2.05, reset release to 1
+ - dropped bugfix patch since Jef included that
+ - streamlined install
+
+* Sun Jul 25 1999 Bennett Todd <bet@mordor.net>
+ - Release 4, added mime type swf
+
+* Mon May 3 1999 Bennett Todd <bet@mordor.net>
+ - Release 2, added patch to set cgi-timelimit up to 10 minutes
+ fm default 30 seconds
+
+* Wed Feb 10 1999 Bennett Todd <bet@mordor.net>
+ - based on 2.00-2, bumped to 2.04, reset release back to 1
+ - fixed a couple of broken entries in %install to reference $RPM_BUILD_ROOT
+ - simplified %files to populate /usr/doc/... with just [A-Z]* (TODO had gone
+ away, this simplification makes it liklier to be trivially portable to
+ future releases).
+ - added %doc tags for the man pages
+
--- /dev/null
+16c41619dbe2621d5592bc2134a67ffe4f585557
--- /dev/null
+Package: thttpd-dbgsym
+Source: thttpd
+Version: 2.29-1
+Auto-Built-Package: debug-symbols
+Architecture: amd64
+Maintainer: Ralph Ronnquist <ralph.ronnquist@gmail.com>
+Installed-Size: 29
+Depends: thttpd (= 2.29-1)
+Section: debug
+Priority: extra
+Homepage: https://acme.com/software/thttpd/
+Description: Debug symbols for thttpd
+Build-Ids: 16c41619dbe2621d5592bc2134a67ffe4f585557
--- /dev/null
+5d5b43817d2c8a05ab36b2706e92f2e4 usr/lib/debug/.build-id/16/c41619dbe2621d5592bc2134a67ffe4f585557.debug
--- /dev/null
+thttpd
\ No newline at end of file
--- /dev/null
+thttpd for Debian
+----------------
+
+<possible notes regarding this package - if none, delete this file>
+
+ -- Ralph Ronnquist <ralph.ronnquist@gmail.com> Sat, 07 Jul 2018 17:38:08 +1000
--- /dev/null
+thttpd for Debian
+----------------
+
+<this file describes information about the source package, see Debian policy
+manual section 4.14. You WILL either need to modify or delete this file>
+
+
+
+ -- Ralph Ronnquist <ralph.ronnquist@gmail.com> Sat, 07 Jul 2018 17:38:08 +1000
+
--- /dev/null
+thttpd (2.29-1) unstable; urgency=medium
+
+ * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
+
+ -- Ralph Ronnquist <ralph.ronnquist@gmail.com> Sat, 07 Jul 2018 17:38:08 +1000
--- /dev/null
+Source: thttpd
+Section: unknown
+Priority: optional
+Maintainer: Ralph Ronnquist <ralph.ronnquist@gmail.com>
+Build-Depends: debhelper (>= 9), autotools-dev
+Standards-Version: 3.9.8
+Homepage: https://acme.com/software/thttpd/
+#Vcs-Git: https://anonscm.debian.org/collab-maint/thttpd.git
+#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/thttpd.git
+
+Package: thttpd
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: tiny/turbo/throttling HTTP server
+ thttpd is a simple, small, portable, fast, and secure HTTP server.
+ .
+ Simple:
+ It handles only the minimum necessary to implement HTTP/1.1. Well, maybe a little more than the minimum.
+ Small:
+ See the comparison chart. It also has a very small run-time size, since it does not fork and is very careful about memory allocation.
+ Portable:
+ It compiles cleanly on most any Unix-like OS, specifically including FreeBSD, SunOS 4, Solaris 2, BSD/OS, Linux, OSF.
+ Fast:
+ In typical use it's about as fast as the best full-featured servers (Apache, NCSA, Netscape). Under extreme load it's much faster.
+ Secure:
+ It goes to great lengths to protect the web server machine against attacks and breakins from other sites.
+ .
+ It also has one extremely useful feature (URL-traffic-based throttling) that no other server currently has. Plus, it supports IPv6 out of the box, no patching required
--- /dev/null
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: thttpd
+Source: <url://example.com>
+
+Files: *
+Copyright: <years> <put author's name and email here>
+ <years> <likewise for another author>
+License: GPL-3.0+
+
+Files: debian/*
+Copyright: 2018 Ralph Ronnquist <ralph.ronnquist@gmail.com>
+License: GPL-3.0+
+
+License: GPL-3.0+
+ 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 package 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 <https://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
+# Please avoid picking licenses with terms that are more restrictive than the
+# packaged work, as it may make Debian's contributions unacceptable upstream.
--- /dev/null
+thttpd-dbgsym_2.29-1_amd64.deb debug extra
+thttpd_2.29-1_amd64.buildinfo unknown optional
+thttpd_2.29-1_amd64.deb unknown optional
--- /dev/null
+.\" Hey, EMACS: -*- nroff -*-
+.\" (C) Copyright 2018 Ralph Ronnquist <ralph.ronnquist@gmail.com>,
+.\"
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH Thttpd SECTION "July 7 2018"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+thttpd \- program to do something
+.SH SYNOPSIS
+.B thttpd
+.RI [ options ] " files" ...
+.br
+.B bar
+.RI [ options ] " files" ...
+.SH DESCRIPTION
+This manual page documents briefly the
+.B thttpd
+and
+.B bar
+commands.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBthttpd\fP is a program that...
+.SH OPTIONS
+These programs follow the usual GNU command line syntax, with long
+options starting with two dashes (`-').
+A summary of options is included below.
+For a complete description, see the Info files.
+.TP
+.B \-h, \-\-help
+Show summary of options.
+.TP
+.B \-v, \-\-version
+Show version of program.
+.SH SEE ALSO
+.BR bar (1),
+.BR baz (1).
+.br
+The programs are documented fully by
+.IR "The Rise and Fall of a Fooish Bar" ,
+available via the Info system.
--- /dev/null
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+
+<!-- Process this file with docbook-to-man to generate an nroff manual
+ page: `docbook-to-man manpage.sgml > manpage.1'. You may view
+ the manual page with: `docbook-to-man manpage.sgml | nroff -man |
+ less'. A typical entry in a Makefile or Makefile.am is:
+
+manpage.1: manpage.sgml
+ docbook-to-man $< > $@
+
+
+ The docbook-to-man binary is found in the docbook-to-man package.
+ Please remember that if you create the nroff version in one of the
+ debian/rules file targets (such as build), you will need to include
+ docbook-to-man in your Build-Depends control field.
+
+ -->
+
+ <!-- Fill in your name for FIRSTNAME and SURNAME. -->
+ <!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
+ <!ENTITY dhsurname "<surname>SURNAME</surname>">
+ <!-- Please adjust the date whenever revising the manpage. -->
+ <!ENTITY dhdate "<date>July 7 2018</date>">
+ <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
+ allowed: see man(7), man(1). -->
+ <!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
+ <!ENTITY dhemail "<email>ralph.ronnquist@gmail.com</email>">
+ <!ENTITY dhusername "Ralph Ronnquist">
+ <!ENTITY dhucpackage "<refentrytitle>Thttpd</refentrytitle>">
+ <!ENTITY dhpackage "thttpd">
+
+ <!ENTITY debian "<productname>Debian</productname>">
+ <!ENTITY gnu "<acronym>GNU</acronym>">
+ <!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
+]>
+
+<refentry>
+ <refentryinfo>
+ <address>
+ &dhemail;
+ </address>
+ <author>
+ &dhfirstname;
+ &dhsurname;
+ </author>
+ <copyright>
+ <year>2003</year>
+ <holder>&dhusername;</holder>
+ </copyright>
+ &dhdate;
+ </refentryinfo>
+ <refmeta>
+ &dhucpackage;
+
+ &dhsection;
+ </refmeta>
+ <refnamediv>
+ <refname>&dhpackage;</refname>
+
+ <refpurpose>program to do something</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>&dhpackage;</command>
+
+ <arg><option>-e <replaceable>this</replaceable></option></arg>
+
+ <arg><option>--example <replaceable>that</replaceable></option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>This manual page documents briefly the
+ <command>&dhpackage;</command> and <command>bar</command>
+ commands.</para>
+
+ <para>This manual page was written for the &debian; distribution
+ because the original program does not have a manual page.
+ Instead, it has documentation in the &gnu;
+ <application>Info</application> format; see below.</para>
+
+ <para><command>&dhpackage;</command> is a program that...</para>
+
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <para>These programs follow the usual &gnu; command line syntax,
+ with long options starting with two dashes (`-'). A summary of
+ options is included below. For a complete description, see the
+ <application>Info</application> files.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-h</option>
+ <option>--help</option>
+ </term>
+ <listitem>
+ <para>Show summary of options.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option>
+ <option>--version</option>
+ </term>
+ <listitem>
+ <para>Show version of program.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+
+ <para>bar (1), baz (1).</para>
+
+ <para>The programs are documented fully by <citetitle>The Rise and
+ Fall of a Fooish Bar</citetitle> available via the
+ <application>Info</application> system.</para>
+ </refsect1>
+ <refsect1>
+ <title>AUTHOR</title>
+
+ <para>This manual page was written by &dhusername; &dhemail; for
+ the &debian; system (and may be used by others). Permission is
+ granted to copy, distribute and/or modify this document under
+ the terms of the &gnu; General Public License, Version 2 any
+ later version published by the Free Software Foundation.
+ </para>
+ <para>
+ On Debian systems, the complete text of the GNU General Public
+ License can be found in /usr/share/common-licenses/GPL.
+ </para>
+
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:nil
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+
+<!--
+
+`xsltproc -''-nonet \
+ -''-param man.charmap.use.subset "0" \
+ -''-param make.year.ranges "1" \
+ -''-param make.single.year.ranges "1" \
+ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl \
+ manpage.xml'
+
+A manual page <package>.<section> will be generated. You may view the
+manual page with: nroff -man <package>.<section> | less'. A typical entry
+in a Makefile or Makefile.am is:
+
+DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl
+XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
+
+manpage.1: manpage.xml
+ $(XP) $(DB2MAN) $<
+
+The xsltproc binary is found in the xsltproc package. The XSL files are in
+docbook-xsl. A description of the parameters you can use can be found in the
+docbook-xsl-doc-* packages. Please remember that if you create the nroff
+version in one of the debian/rules file targets (such as build), you will need
+to include xsltproc and docbook-xsl in your Build-Depends control field.
+Alternatively use the xmlto command/package. That will also automatically
+pull in xsltproc and docbook-xsl.
+
+Notes for using docbook2x: docbook2x-man does not automatically create the
+AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as
+<refsect1> ... </refsect1>.
+
+To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections
+read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be
+found in the docbook-xsl-doc-html package.
+
+Validation can be done using: `xmllint -''-noout -''-valid manpage.xml`
+
+General documentation about man-pages and man-page-formatting:
+man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
+
+-->
+
+ <!-- Fill in your name for FIRSTNAME and SURNAME. -->
+ <!ENTITY dhfirstname "FIRSTNAME">
+ <!ENTITY dhsurname "SURNAME">
+ <!-- dhusername could also be set to "&dhfirstname; &dhsurname;". -->
+ <!ENTITY dhusername "Ralph Ronnquist">
+ <!ENTITY dhemail "ralph.ronnquist@gmail.com">
+ <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
+ allowed: see man(7), man(1) and
+ http://www.tldp.org/HOWTO/Man-Page/q2.html. -->
+ <!ENTITY dhsection "SECTION">
+ <!-- TITLE should be something like "User commands" or similar (see
+ http://www.tldp.org/HOWTO/Man-Page/q2.html). -->
+ <!ENTITY dhtitle "thttpd User Manual">
+ <!ENTITY dhucpackage "Thttpd">
+ <!ENTITY dhpackage "thttpd">
+]>
+
+<refentry>
+ <refentryinfo>
+ <title>&dhtitle;</title>
+ <productname>&dhpackage;</productname>
+ <authorgroup>
+ <author>
+ <firstname>&dhfirstname;</firstname>
+ <surname>&dhsurname;</surname>
+ <contrib>Wrote this manpage for the Debian system.</contrib>
+ <address>
+ <email>&dhemail;</email>
+ </address>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2007</year>
+ <holder>&dhusername;</holder>
+ </copyright>
+ <legalnotice>
+ <para>This manual page was written for the Debian system
+ (and may be used by others).</para>
+ <para>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the GNU General Public License,
+ Version 2 or (at your option) any later version published by
+ the Free Software Foundation.</para>
+ <para>On Debian systems, the complete text of the GNU General Public
+ License can be found in
+ <filename>/usr/share/common-licenses/GPL</filename>.</para>
+ </legalnotice>
+ </refentryinfo>
+ <refmeta>
+ <refentrytitle>&dhucpackage;</refentrytitle>
+ <manvolnum>&dhsection;</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>&dhpackage;</refname>
+ <refpurpose>program to do something</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>&dhpackage;</command>
+ <!-- These are several examples, how syntaxes could look -->
+ <arg choice="plain"><option>-e <replaceable>this</replaceable></option></arg>
+ <arg choice="opt"><option>--example=<parameter>that</parameter></option></arg>
+ <arg choice="opt">
+ <group choice="req">
+ <arg choice="plain"><option>-e</option></arg>
+ <arg choice="plain"><option>--example</option></arg>
+ </group>
+ <replaceable class="option">this</replaceable>
+ </arg>
+ <arg choice="opt">
+ <group choice="req">
+ <arg choice="plain"><option>-e</option></arg>
+ <arg choice="plain"><option>--example</option></arg>
+ </group>
+ <group choice="req">
+ <arg choice="plain"><replaceable>this</replaceable></arg>
+ <arg choice="plain"><replaceable>that</replaceable></arg>
+ </group>
+ </arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>&dhpackage;</command>
+ <!-- Normally the help and version options make the programs stop
+ right after outputting the requested information. -->
+ <group choice="opt">
+ <arg choice="plain">
+ <group choice="req">
+ <arg choice="plain"><option>-h</option></arg>
+ <arg choice="plain"><option>--help</option></arg>
+ </group>
+ </arg>
+ <arg choice="plain">
+ <group choice="req">
+ <arg choice="plain"><option>-v</option></arg>
+ <arg choice="plain"><option>--version</option></arg>
+ </group>
+ </arg>
+ </group>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1 id="description">
+ <title>DESCRIPTION</title>
+ <para>This manual page documents briefly the
+ <command>&dhpackage;</command> and <command>bar</command>
+ commands.</para>
+ <para>This manual page was written for the Debian distribution
+ because the original program does not have a manual page.
+ Instead, it has documentation in the GNU <citerefentry>
+ <refentrytitle>info</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry> format; see below.</para>
+ <para><command>&dhpackage;</command> is a program that...</para>
+ </refsect1>
+ <refsect1 id="options">
+ <title>OPTIONS</title>
+ <para>The program follows the usual GNU command line syntax,
+ with long options starting with two dashes (`-'). A summary of
+ options is included below. For a complete description, see the
+ <citerefentry>
+ <refentrytitle>info</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry> files.</para>
+ <variablelist>
+ <!-- Use the variablelist.term.separator and the
+ variablelist.term.break.after parameters to
+ control the term elements. -->
+ <varlistentry>
+ <term><option>-e <replaceable>this</replaceable></option></term>
+ <term><option>--example=<replaceable>that</replaceable></option></term>
+ <listitem>
+ <para>Does this and that.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option></term>
+ <term><option>--help</option></term>
+ <listitem>
+ <para>Show summary of options.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option></term>
+ <term><option>--version</option></term>
+ <listitem>
+ <para>Show version of program.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1 id="files">
+ <title>FILES</title>
+ <variablelist>
+ <varlistentry>
+ <term><filename>/etc/foo.conf</filename></term>
+ <listitem>
+ <para>The system-wide configuration file to control the
+ behaviour of <application>&dhpackage;</application>. See
+ <citerefentry>
+ <refentrytitle>foo.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry> for further details.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><filename>${HOME}/.foo.conf</filename></term>
+ <listitem>
+ <para>The per-user configuration file to control the
+ behaviour of <application>&dhpackage;</application>. See
+ <citerefentry>
+ <refentrytitle>foo.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry> for further details.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1 id="environment">
+ <title>ENVIRONMENT</title>
+ <variablelist>
+ <varlistentry>
+ <term><envar>FOO_CONF</envar></term>
+ <listitem>
+ <para>If used, the defined file is used as configuration
+ file (see also <xref linkend="files"/>).</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1 id="diagnostics">
+ <title>DIAGNOSTICS</title>
+ <para>The following diagnostics may be issued
+ on <filename class="devicefile">stderr</filename>:</para>
+ <variablelist>
+ <varlistentry>
+ <term><errortext>Bad configuration file. Exiting.</errortext></term>
+ <listitem>
+ <para>The configuration file seems to contain a broken configuration
+ line. Use the <option>--verbose</option> option, to get more info.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para><command>&dhpackage;</command> provides some return codes, that can
+ be used in scripts:</para>
+ <segmentedlist>
+ <segtitle>Code</segtitle>
+ <segtitle>Diagnostic</segtitle>
+ <seglistitem>
+ <seg><errorcode>0</errorcode></seg>
+ <seg>Program exited successfully.</seg>
+ </seglistitem>
+ <seglistitem>
+ <seg><errorcode>1</errorcode></seg>
+ <seg>The configuration file seems to be broken.</seg>
+ </seglistitem>
+ </segmentedlist>
+ </refsect1>
+ <refsect1 id="bugs">
+ <!-- Or use this section to tell about upstream BTS. -->
+ <title>BUGS</title>
+ <para>The program is currently limited to only work
+ with the <package>foobar</package> library.</para>
+ <para>The upstreams <acronym>BTS</acronym> can be found
+ at <ulink url="http://bugzilla.foo.tld"/>.</para>
+ </refsect1>
+ <refsect1 id="see_also">
+ <title>SEE ALSO</title>
+ <!-- In alpabetical order. -->
+ <para><citerefentry>
+ <refentrytitle>bar</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>, <citerefentry>
+ <refentrytitle>baz</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>, <citerefentry>
+ <refentrytitle>foo.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry></para>
+ <para>The programs are documented fully by <citetitle>The Rise and
+ Fall of a Fooish Bar</citetitle> available via the <citerefentry>
+ <refentrytitle>info</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry> system.</para>
+ </refsect1>
+</refentry>
+
--- /dev/null
+?package(thttpd):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\
+ title="thttpd" command="/usr/bin/thttpd"
--- /dev/null
+#!/bin/sh
+# postinst script for thttpd
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/bin/sh
+# postrm script for thttpd
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postrm> `remove'
+# * <postrm> `purge'
+# * <old-postrm> `upgrade' <new-version>
+# * <new-postrm> `failed-upgrade' <old-version>
+# * <new-postrm> `abort-install'
+# * <new-postrm> `abort-install' <old-version>
+# * <new-postrm> `abort-upgrade' <old-version>
+# * <disappearer's-postrm> `disappear' <overwriter>
+# <overwriter-version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+ ;;
+
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/bin/sh
+# preinst script for thttpd
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <new-preinst> `install'
+# * <new-preinst> `install' <old-version>
+# * <new-preinst> `upgrade' <old-version>
+# * <old-preinst> `abort-upgrade' <new-version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ install|upgrade)
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/bin/sh
+# prerm script for thttpd
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <prerm> `remove'
+# * <old-prerm> `upgrade' <new-version>
+# * <new-prerm> `failed-upgrade' <old-version>
+# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+# * <deconfigured's-prerm> `deconfigure' `in-favour'
+# <package-being-installed> <version> `removing'
+# <conflicting-package> <version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/usr/bin/make -f
+# See debhelper(7) (uncomment to enable)
+# output every command that modifies files on the build system.
+export DH_VERBOSE = 1
+
+# see FEATURE AREAS in dpkg-buildflags(1)
+#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+# see ENVIRONMENT in dpkg-buildflags(1)
+# package maintainers to append CFLAGS
+#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
+# package maintainers to append LDFLAGS
+#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
+
+%:
+ dh $@ --with autotools_dev --without systemd
+
+# dh_make generated override targets
+# This is example for Cmake (See https://bugs.debian.org/641051 )
+override_dh_auto_configure:
+ dh_auto_configure -- --prefix=/usr/local --mandir=/usr/local/man
+
+override_dh_usrlocal:
--- /dev/null
+3.0 (quilt)
--- /dev/null
+README.source
+README.Debian
--- /dev/null
+#
+# Regular cron jobs for the thttpd package
+#
+0 4 * * * root [ -x /usr/bin/thttpd_maintenance ] && /usr/bin/thttpd_maintenance
--- /dev/null
+dh_update_autotools_config
+dh_autotools-dev_updateconfig
+override_dh_auto_configure dh_auto_configure
+dh_auto_configure
+dh_auto_build
+dh_auto_test
+dh_prep
+dh_auto_install
+dh_installdocs
+dh_installchangelogs
+dh_perl
+dh_link
+dh_strip_nondeterminism
+dh_compress
+dh_fixperms
+dh_strip
+dh_makeshlibs
+dh_shlibdeps
+dh_installdeb
+dh_gencontrol
+dh_md5sums
+dh_builddeb
+dh_builddeb
--- /dev/null
+# Defaults for thttpd initscript
+# sourced by /etc/init.d/thttpd
+# installed at /etc/default/thttpd by the maintainer scripts
+
+#
+# This is a POSIX shell fragment
+#
+
+# Additional options that are passed to the Daemon.
+DAEMON_OPTS=""
--- /dev/null
+Document: thttpd
+Title: Debian thttpd Manual
+Author: <insert document author here>
+Abstract: This manual describes what thttpd is
+ and how it can be used to
+ manage online manuals on Debian systems.
+Section: unknown
+
+Format: debiandoc-sgml
+Files: /usr/share/doc/thttpd/thttpd.sgml.gz
+
+Format: postscript
+Files: /usr/share/doc/thttpd/thttpd.ps.gz
+
+Format: text
+Files: /usr/share/doc/thttpd/thttpd.text.gz
+
+Format: HTML
+Index: /usr/share/doc/thttpd/html/index.html
+Files: /usr/share/doc/thttpd/html/*.html
--- /dev/null
+shlibs:Depends=libc6 (>= 2.7)
+misc:Depends=
+misc:Pre-Depends=
--- /dev/null
+Package: thttpd
+Version: 2.29-1
+Architecture: amd64
+Maintainer: Ralph Ronnquist <ralph.ronnquist@gmail.com>
+Installed-Size: 140
+Depends: libc6 (>= 2.7)
+Section: unknown
+Priority: optional
+Homepage: https://acme.com/software/thttpd/
+Description: tiny/turbo/throttling HTTP server
+ thttpd is a simple, small, portable, fast, and secure HTTP server.
+ .
+ Simple:
+ It handles only the minimum necessary to implement HTTP/1.1. Well, maybe a little more than the minimum.
+ Small:
+ See the comparison chart. It also has a very small run-time size, since it does not fork and is very careful about memory allocation.
+ Portable:
+ It compiles cleanly on most any Unix-like OS, specifically including FreeBSD, SunOS 4, Solaris 2, BSD/OS, Linux, OSF.
+ Fast:
+ In typical use it's about as fast as the best full-featured servers (Apache, NCSA, Netscape). Under extreme load it's much faster.
+ Secure:
+ It goes to great lengths to protect the web server machine against attacks and breakins from other sites.
+ .
+ It also has one extremely useful feature (URL-traffic-based throttling) that no other server currently has. Plus, it supports IPv6 out of the box, no patching required
--- /dev/null
+a26b763da2e1d7b8a43ff034891ad109 usr/local/man/man8/thttpd.8
+59e42258ea3cc0f440729feba8bf7d73 usr/local/sbin/thttpd
+a4c701db3345a7c9a7c6deb32338e915 usr/share/doc/thttpd/README.Debian
+a578191a808074968cb7b02afac0c55f usr/share/doc/thttpd/changelog.Debian.gz
+88dda395d0decd5e5a07521e4ca02be3 usr/share/doc/thttpd/copyright
--- /dev/null
+.TH thttpd 8 "29 February 2000"
+.SH NAME
+thttpd - tiny/turbo/throttling HTTP server
+.SH SYNOPSIS
+.B thttpd
+.RB [ -C
+.IR configfile ]
+.RB [ -p
+.IR port ]
+.RB [ -d
+.IR dir ]
+.RB [ -dd
+.IR data_dir ]
+.RB [ -r | -nor ]
+.RB [ -s | -nos ]
+.RB [ -v | -nov ]
+.RB [ -g | -nog ]
+.RB [ -u
+.IR user ]
+.RB [ -c
+.IR cgipat ]
+.RB [ -t
+.IR throttles ]
+.RB [ -h
+.IR host ]
+.RB [ -l
+.IR logfile ]
+.RB [ -i
+.IR pidfile ]
+.RB [ -T
+.IR charset ]
+.RB [ -P
+.IR P3P ]
+.RB [ -M
+.IR maxage ]
+.RB [ -V ]
+.RB [ -D ]
+.SH DESCRIPTION
+.PP
+.I thttpd
+is a simple, small, fast, and secure HTTP server.
+It doesn't have a lot of special features, but it suffices for most uses of
+the web, it's about as fast as the best full-featured servers (Apache, NCSA,
+Netscape),
+and it has one extremely useful feature (URL-traffic-based throttling)
+that no other server currently has.
+.SH OPTIONS
+.TP
+.B -C
+Specifies a config-file to read.
+All options can be set either by command-line flags or in the config file.
+See below for details.
+.TP
+.B -p
+Specifies an alternate port number to listen on.
+The default is 80.
+The config-file option name for this flag is "port",
+and the config.h option is DEFAULT_PORT.
+.TP
+.B -d
+Specifies a directory to chdir() to at startup.
+This is merely a convenience - you could just as easily
+do a cd in the shell script that invokes the program.
+The config-file option name for this flag is "dir",
+and the config.h options are WEBDIR, USE_USER_DIR.
+.TP
+.B -r
+Do a chroot() at initialization time, restricting file access
+to the program's current directory.
+If -r is the compiled-in default, then -nor disables it.
+See below for details.
+The config-file option names for this flag are "chroot" and "nochroot",
+and the config.h option is ALWAYS_CHROOT.
+.TP
+.B -dd
+Specifies a directory to chdir() to after chrooting.
+If you're not chrooting, you might as well do a single chdir() with
+the -d flag.
+If you are chrooting, this lets you put the web files in a subdirectory
+of the chroot tree, instead of in the top level mixed in with the
+chroot files.
+The config-file option name for this flag is "data_dir".
+.TP
+.B -nos
+Don't do explicit symbolic link checking.
+Normally, thttpd explicitly expands any symbolic links in filenames,
+to check that the resulting path stays within the original document tree.
+If you want to turn off this check and save some CPU time, you can use
+the -nos flag, however this is not recommended.
+Note, though, that if you are using the chroot option, the symlink
+checking is unnecessary and is turned off, so the safe way to save
+those CPU cycles is to use chroot.
+The config-file option names for this flag are "symlinkcheck" and "nosymlinkcheck".
+.TP
+.B -v
+Do el-cheapo virtual hosting.
+If -v is the compiled-in default, then -nov disables it.
+See below for details.
+The config-file option names for this flag are "vhost" and "novhost",
+and the config.h option is ALWAYS_VHOST.
+.TP
+.B -g
+Use a global passwd file.
+This means that every file in the entire document tree is protected by
+the single .htpasswd file at the top of the tree.
+Otherwise the semantics of the .htpasswd file are the same.
+If this option is set but there is no .htpasswd file in
+the top-level directory, then thttpd proceeds as if the option was
+not set - first looking for a local .htpasswd file, and if that doesn't
+exist either then serving the file without any password.
+If -g is the compiled-in default, then -nog disables it.
+The config-file option names for this flag are "globalpasswd" and
+"noglobalpasswd",
+and the config.h option is ALWAYS_GLOBAL_PASSWD.
+.TP
+.B -u
+Specifies what user to switch to after initialization when started as root.
+The default is "nobody".
+The config-file option name for this flag is "user",
+and the config.h option is DEFAULT_USER.
+.TP
+.B -c
+Specifies a wildcard pattern for CGI programs, for instance "**.cgi"
+or "/cgi-bin/*".
+See below for details.
+The config-file option name for this flag is "cgipat",
+and the config.h option is CGI_PATTERN.
+.TP
+.B -t
+Specifies a file of throttle settings.
+See below for details.
+The config-file option name for this flag is "throttles".
+.TP
+.B -h
+Specifies a hostname to bind to, for multihoming.
+The default is to bind to all hostnames supported on the local machine.
+See below for details.
+The config-file option name for this flag is "host",
+and the config.h option is SERVER_NAME.
+.TP
+.B -l
+Specifies a file for logging.
+If no -l argument is specified, thttpd logs via syslog().
+If "-l /dev/null" is specified, thttpd doesn't log at all.
+The config-file option name for this flag is "logfile".
+.TP
+.B -i
+Specifies a file to write the process-id to.
+If no file is specified, no process-id is written.
+You can use this file to send signals to thttpd.
+See below for details.
+The config-file option name for this flag is "pidfile".
+.TP
+.B -T
+Specifies the character set to use with text MIME types.
+The default is UTF-8.
+The config-file option name for this flag is "charset",
+and the config.h option is DEFAULT_CHARSET.
+.TP
+.B -P
+Specifies a P3P server privacy header to be returned with all responses.
+See http://www.w3.org/P3P/ for details.
+Thttpd doesn't do anything at all with the string except put it in the
+P3P: response header.
+The config-file option name for this flag is "p3p".
+.TP
+.B -M
+Specifies the number of seconds to be used in a "Cache-Control: max-age"
+header to be returned with all responses.
+An equivalent "Expires" header is also generated.
+The default is no Cache-Control or Expires headers,
+which is just fine for most sites.
+The config-file option name for this flag is "max_age".
+.TP
+.B -V
+Shows the current version info.
+.TP
+.B -D
+This was originally just a debugging flag, however it's worth mentioning
+because one of the things it does is prevent thttpd from making itself
+a background daemon.
+Instead it runs in the foreground like a regular program.
+This is necessary when you want to run thttpd wrapped in a little shell
+script that restarts it if it exits.
+.SH "CONFIG-FILE"
+.PP
+All the command-line options can also be set in a config file.
+One advantage of using a config file is that the file can be changed,
+and thttpd will pick up the changes with a restart.
+.PP
+The syntax of the config file is simple, a series of "option" or
+"option=value" separated by whitespace.
+The option names are listed above with their corresponding command-line flags.
+.SH "CHROOT"
+.PP
+chroot() is a system call that restricts the program's view
+of the filesystem to the current directory and directories
+below it.
+It becomes impossible for remote users to access any file
+outside of the initial directory.
+The restriction is inherited by child processes, so CGI programs get it too.
+This is a very strong security measure, and is recommended.
+The only downside is that only root can call chroot(), so this means
+the program must be started as root.
+However, the last thing it does during initialization is to
+give up root access by becoming another user, so this is safe.
+.PP
+The program can also be compile-time configured to always
+do a chroot(), without needing the -r flag.
+.PP
+Note that with some other web servers, such as NCSA httpd, setting
+up a directory tree for use with chroot() is complicated, involving
+creating a bunch of special directories and copying in various files.
+With thttpd it's a lot easier, all you have to do is make sure
+any shells, utilities, and config files used by your CGI programs and
+scripts are available.
+If you have CGI disabled, or if you make a policy that all CGI programs
+must be written in a compiled language such as C and statically linked,
+then you probably don't have to do any setup at all.
+.PP
+However, one thing you should do is tell syslogd about the chroot tree,
+so that thttpd can still generate syslog messages.
+Check your system's syslodg man page for how to do this.
+In FreeBSD you would put something like this in /etc/rc.conf:
+.nf
+ syslogd_flags="-l /usr/local/www/data/dev/log"
+.fi
+Substitute in your own chroot tree's pathname, of course.
+Don't worry about creating the log socket, syslogd wants to do that itself.
+(You may need to create the dev directory.)
+In Linux the flag is -a instead of -l, and there may be other differences.
+.PP
+Relevant config.h option: ALWAYS_CHROOT.
+.SH "CGI"
+.PP
+thttpd supports the CGI 1.1 spec.
+.PP
+In order for a CGI program to be run, its name must match the pattern
+specified either at compile time or on the command line with the -c flag.
+This is a simple shell-style filename pattern.
+You can use * to match any string not including a slash,
+or ** to match any string including slashes,
+or ? to match any single character.
+You can also use multiple such patterns separated by |.
+The patterns get checked against the filename
+part of the incoming URL.
+Don't forget to quote any wildcard characters so that the shell doesn't
+mess with them.
+.PP
+Restricting CGI programs to a single directory lets the site administrator
+review them for security holes, and is strongly recommended.
+If there are individual users that you trust, you can enable their
+directories too.
+.PP
+If no CGI pattern is specified, neither here nor at compile time,
+then CGI programs cannot be run at all.
+If you want to disable CGI as a security measure, that's how you do it, just
+comment out the patterns in the config file and don't run with the -c flag.
+.PP
+Note: the current working directory when a CGI program gets run is
+the directory that the CGI program lives in.
+This isn't in the CGI 1.1 spec, but it's what most other HTTP servers do.
+.PP
+Relevant config.h options: CGI_PATTERN, CGI_TIMELIMIT, CGI_NICE, CGI_PATH, CGI_LD_LIBRARY_PATH, CGIBINDIR.
+.SH "BASIC AUTHENTICATION"
+.PP
+Basic Authentication is available as an option at compile time.
+If enabled, it uses a password file in the directory to be protected,
+called .htpasswd by default.
+This file is formatted as the familiar colon-separated
+username/encrypted-password pair, records delimited by newlines.
+The protection does not carry over to subdirectories.
+The utility program htpasswd(1) is included to help create and
+modify .htpasswd files.
+.PP
+Relevant config.h option: AUTH_FILE
+.SH "THROTTLING"
+.PP
+The throttle file lets you set maximum byte rates on URLs or URL groups.
+You can optionally set a minimum rate too.
+The format of the throttle file is very simple.
+A # starts a comment, and the rest of the line is ignored.
+Blank lines are ignored.
+The rest of the lines should consist of a pattern, whitespace, and a number.
+The pattern is a simple shell-style filename pattern, using ?/**/*, or
+multiple such patterns separated by |.
+.PP
+The numbers in the file are byte rates, specified in units of bytes per second.
+For comparison, a v.90 modem gives about 5000 B/s depending on compression,
+a double-B-channel ISDN line about 12800 B/s, and a T1 line is about
+150000 B/s.
+If you want to set a minimum rate as well, use number-number.
+.PP
+Example:
+.nf
+ # throttle file for www.acme.com
+
+ ** 2000-100000 # limit total web usage to 2/3 of our T1,
+ # but never go below 2000 B/s
+ **.jpg|**.gif 50000 # limit images to 1/3 of our T1
+ **.mpg 20000 # and movies to even less
+ jef/** 20000 # jef's pages are too popular
+.fi
+.PP
+Throttling is implemented by checking each incoming URL filename against all
+of the patterns in the throttle file.
+The server accumulates statistics on how much bandwidth each pattern
+has accounted for recently (via a rolling average).
+If a URL matches a pattern that has been exceeding its specified limit,
+then the data returned is actually slowed down, with
+pauses between each block.
+If that's not possible (e.g. for CGI programs) or if the bandwidth has gotten
+way larger than the limit, then the server returns a special code
+saying 'try again later'.
+.PP
+The minimum rates are implemented similarly.
+If too many people are trying to fetch something at the same time,
+throttling may slow down each connection so much that it's not really
+useable.
+Furthermore, all those slow connections clog up the server, using
+up file handles and connection slots.
+Setting a minimum rate says that past a certain point you should not
+even bother - the server returns the 'try again later" code and the
+connection isn't even started.
+.PP
+There is no provision for setting a maximum connections/second throttle,
+because throttling a request uses as much cpu as handling it, so
+there would be no point.
+There is also no provision for throttling the number of simultaneous
+connections on a per-URL basis.
+However you can control the overall number of connections for the whole
+server very simply, by setting the operating system's per-process file
+descriptor limit before starting thttpd.
+Be sure to set the hard limit, not the soft limit.
+.SH "MULTIHOMING"
+.PP
+Multihoming means using one machine to serve multiple hostnames.
+For instance, if you're an internet provider and you want to let
+all of your customers have customized web addresses, you might
+have www.joe.acme.com, www.jane.acme.com, and your own www.acme.com,
+all running on the same physical hardware.
+This feature is also known as "virtual hosts".
+There are three steps to setting this up.
+.PP
+One, make DNS entries for all of the hostnames.
+The current way to do this, allowed by HTTP/1.1, is to use CNAME aliases,
+like so:
+.nf
+ www.acme.com IN A 192.100.66.1
+ www.joe.acme.com IN CNAME www.acme.com
+ www.jane.acme.com IN CNAME www.acme.com
+.fi
+However, this is incompatible with older HTTP/1.0 browsers.
+If you want to stay compatible, there's a different way - use A records
+instead, each with a different IP address, like so:
+.nf
+ www.acme.com IN A 192.100.66.1
+ www.joe.acme.com IN A 192.100.66.200
+ www.jane.acme.com IN A 192.100.66.201
+.fi
+This is bad because it uses extra IP addresses, a somewhat scarce resource.
+But if you want people with older browsers to be able to visit your
+sites, you still have to do it this way.
+.PP
+Step two.
+If you're using the modern CNAME method of multihoming, then you can
+skip this step.
+Otherwise, using the older multiple-IP-address method you
+must set up IP aliases or multiple interfaces for the extra addresses.
+You can use ifconfig(8)'s alias command to tell the machine to answer to
+all of the different IP addresses.
+Example:
+.nf
+ ifconfig le0 www.acme.com
+ ifconfig le0 www.joe.acme.com alias
+ ifconfig le0 www.jane.acme.com alias
+.fi
+If your OS's version of ifconfig doesn't have an alias command, you're
+probably out of luck (but see http://www.acme.com/software/thttpd/notes.html).
+.PP
+Third and last, you must set up thttpd to handle the multiple hosts.
+The easiest way is with the -v flag, or the ALWAYS_VHOST config.h option.
+This works with either CNAME multihosting or multiple-IP multihosting.
+What it does is send each incoming request to a subdirectory based on the
+hostname it's intended for.
+All you have to do in order to set things up is to create those subdirectories
+in the directory where thttpd will run.
+With the example above, you'd do like so:
+.nf
+ mkdir www.acme.com www.joe.acme.com www.jane.acme.com
+.fi
+If you're using old-style multiple-IP multihosting, you should also create
+symbolic links from the numeric addresses to the names, like so:
+.nf
+ ln -s www.acme.com 192.100.66.1
+ ln -s www.joe.acme.com 192.100.66.200
+ ln -s www.jane.acme.com 192.100.66.201
+.fi
+This lets the older HTTP/1.0 browsers find the right subdirectory.
+.PP
+There's an optional alternate step three if you're using multiple-IP
+multihosting: run a separate thttpd process for each hostname, using
+the -h flag to specify which one is which.
+This gives you more flexibility, since you can run each of these processes
+in separate directories, with different throttle files, etc.
+Example:
+.nf
+ thttpd -r -d /usr/www -h www.acme.com
+ thttpd -r -d /usr/www/joe -u joe -h www.joe.acme.com
+ thttpd -r -d /usr/www/jane -u jane -h www.jane.acme.com
+.fi
+But remember, this multiple-process method does not work with CNAME
+multihosting - for that, you must use a single thttpd process with
+the -v flag.
+.SH "CUSTOM ERRORS"
+.PP
+thttpd lets you define your own custom error pages for the various
+HTTP errors.
+There's a separate file for each error number, all stored in one
+special directory.
+The directory name is "errors", at the top of the web directory tree.
+The error files should be named "errNNN.html", where NNN is the error number.
+So for example, to make a custom error page for the authentication failure
+error, which is number 401, you would put your HTML into the file
+"errors/err401.html".
+If no custom error file is found for a given error number, then the
+usual built-in error page is generated.
+.PP
+If you're using the virtual hosts option, you can also have different
+custom error pages for each different virtual host.
+In this case you put another "errors" directory in the top of that
+virtual host's web tree.
+thttpd will look first in the virtual host errors directory, and
+then in the server-wide errors directory, and if neither of those
+has an appropriate error file then it will generate the built-in error.
+.SH "NON-LOCAL REFERRERS"
+.PP
+Sometimes another site on the net will embed your image files in their
+HTML files, which basically means they're stealing your bandwidth.
+You can prevent them from doing this by using non-local referrer filtering.
+With this option, certain files can only be fetched via a local referrer.
+The files have to be referenced by a local web page.
+If a web page on some other site references the files, that fetch will
+be blocked.
+There are three config-file variables for this feature:
+.TP
+.B urlpat
+A wildcard pattern for the URLs that should require a local referrer.
+This is typically just image files, sound files, and so on.
+For example:
+.nf
+ urlpat=**.jpg|**.gif|**.au|**.wav
+.fi
+For most sites, that one setting is all you need to enable referrer filtering.
+.TP
+.B noemptyreferrers
+By default, requests with no referrer at all, or a null referrer, or a
+referrer with no apparent hostname, are allowed.
+With this variable set, such requests are disallowed.
+.TP
+.B localpat
+A wildcard pattern that specifies the local host or hosts.
+This is used to determine if the host in the referrer is local or not.
+If not specified it defaults to the actual local hostname.
+.SH SYMLINKS
+.PP
+thttpd is very picky about symbolic links.
+Before delivering any file, it first checks each element in the path
+to see if it's a symbolic link, and expands them all out to get the final
+actual filename.
+Along the way it checks for things like links with ".." that go above
+the server's directory, and absolute symlinks (ones that start with a /).
+These are prohibited as security holes, so the server returns an
+error page for them.
+This means you can't set up your web directory with a bunch of symlinks
+pointing to individual users' home web directories.
+Instead you do it the other way around - the user web directories are
+real subdirs of the main web directory, and in each user's home
+dir there's a symlink pointing to their actual web dir.
+.PP
+The CGI pattern is also affected - it gets matched against the fully-expanded
+filename. So, if you have a single CGI directory but then put a symbolic
+link in it pointing somewhere else, that won't work. The CGI program will be
+treated as a regular file and returned to the client, instead of getting run.
+This could be confusing.
+.SH PERMISSIONS
+.PP
+thttpd is also picky about file permissions.
+It wants data files (HTML, images) to be world readable.
+Readable by the group that the thttpd process runs as is not enough - thttpd
+checks explicitly for the world-readable bit.
+This is so that no one ever gets surprised by a file that's not set
+world-readable and yet somehow is readable by the HTTP server and
+therefore the *whole* world.
+.PP
+The same logic applies to directories.
+As with the standard Unix "ls" program, thttpd will only let you
+look at the contents of a directory if its read bit is on; but
+as with data files, this must be the world-read bit, not just the
+group-read bit.
+.PP
+thttpd also wants the execute bit to be *off* for data files.
+A file that is marked executable but doesn't match the CGI pattern
+might be a script or program that got accidentally left in the
+wrong directory.
+Allowing people to fetch the contents of the file might be a security breach,
+so this is prohibited.
+Of course if an executable file *does* match the CGI pattern, then it
+just gets run as a CGI.
+.PP
+In summary, data files should be mode 644 (rw-r--r--),
+directories should be 755 (rwxr-xr-x) if you want to allow indexing and
+711 (rwx--x--x) to disallow it, and CGI programs should be mode
+755 (rwxr-xr-x) or 711 (rwx--x--x).
+.SH LOGS
+.PP
+thttpd does all of its logging via syslog(3).
+The facility it uses is configurable.
+Aside from error messages, there are only a few log entry types of interest,
+all fairly similar to CERN Common Log Format:
+.nf
+ Aug 6 15:40:34 acme thttpd[583]: 165.113.207.103 - - "GET /file" 200 357
+ Aug 6 15:40:43 acme thttpd[583]: 165.113.207.103 - - "HEAD /file" 200 0
+ Aug 6 15:41:16 acme thttpd[583]: referrer http://www.acme.com/ -> /dir
+ Aug 6 15:41:16 acme thttpd[583]: user-agent Mozilla/1.1N
+.fi
+The package includes a script for translating these log entries info
+CERN-compatible files.
+Note that thttpd does not translate numeric IP addresses into domain names.
+This is both to save time and as a minor security measure (the numeric
+address is harder to spoof).
+.PP
+Relevant config.h option: LOG_FACILITY.
+.PP
+If you'd rather log directly to a file, you can use the -l command-line
+flag. But note that error messages still go to syslog.
+.SH SIGNALS
+.PP
+thttpd handles a couple of signals, which you can send via the
+standard Unix kill(1) command:
+.TP
+.B INT,TERM
+These signals tell thttpd to shut down immediately.
+Any requests in progress get aborted.
+.TP
+.B USR1
+This signal tells thttpd to shut down as soon as it's done servicing
+all current requests.
+In addition, the network socket it uses to accept new connections gets
+closed immediately, which means a fresh thttpd can be started up
+immediately.
+.TP
+.B USR2
+This signal tells thttpd to generate the statistics syslog messages
+immediately, instead of waiting for the regular hourly update.
+.TP
+.B HUP
+This signal tells thttpd to close and re-open its (non-syslog) log file,
+for instance if you rotated the logs and want it to start using the
+new one.
+This is a little tricky to set up correctly, for instance if you are using
+chroot() then the log file must be within the chroot tree, but it's
+definitely doable.
+.SH "SEE ALSO"
+redirect(8), ssi(8), makeweb(1), htpasswd(1), syslogtocern(8), weblog_parse(1), http_get(1)
+.SH THANKS
+.PP
+Many thanks to contributors, reviewers, testers:
+John LoVerso, Jordan Hayes, Chris Torek, Jim Thompson, Barton Schaffer,
+Geoff Adams, Dan Kegel, John Hascall, Bennett Todd, KIKUCHI Takahiro,
+Catalin Ionescu.
+Special thanks to Craig Leres for substantial debugging and development,
+and for not complaining about my coding style very much.
+.SH AUTHOR
+Copyright © 1995,1998,1999,2000 by Jef Poskanzer <jef@mail.acme.com>.
+All rights reserved.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
--- /dev/null
+thttpd for Debian
+----------------
+
+<possible notes regarding this package - if none, delete this file>
+
+ -- Ralph Ronnquist <ralph.ronnquist@gmail.com> Sat, 07 Jul 2018 17:38:08 +1000
--- /dev/null
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: thttpd
+Source: <url://example.com>
+
+Files: *
+Copyright: <years> <put author's name and email here>
+ <years> <likewise for another author>
+License: GPL-3.0+
+
+Files: debian/*
+Copyright: 2018 Ralph Ronnquist <ralph.ronnquist@gmail.com>
+License: GPL-3.0+
+
+License: GPL-3.0+
+ 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 package 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 <https://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
+# Please avoid picking licenses with terms that are more restrictive than the
+# packaged work, as it may make Debian's contributions unacceptable upstream.
--- /dev/null
+# Example watch control file for uscan
+# Rename this file to "watch" and then you can run the "uscan" command
+# to check for upstream updates and more.
+# See uscan(1) for format
+
+# Compulsory line, this is a version 4 file
+version=4
+
+# PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig
+#opts="pgpsigurlmangle=s%$%.sig%"
+
+# HTTP site (basic)
+#http://example.com/downloads.html \
+# files/thttpd-([\d\.]+)\.tar\.gz debian uupdate
+
+# Uncommment to examine a FTP server
+#ftp://ftp.example.com/pub/thttpd-(.*)\.tar\.gz debian uupdate
+
+# SourceForge hosted projects
+# http://sf.net/thttpd/ thttpd-(.*)\.tar\.gz debian uupdate
+
+# GitHub hosted projects
+#opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
+# https://github.com/<user>/thttpd/tags \
+# (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
+
+# PyPI
+# https://pypi.debian.net/thttpd/thttpd-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
+
+# Direct Git
+# opts="mode=git" http://git.example.com/thttpd.git \
+# refs/tags/v([\d\.]+) debian uupdate
+
+
+
+
+# Uncomment to find new files on GooglePages
+# http://example.googlepages.com/foo.html thttpd-(.*)\.tar\.gz
--- /dev/null
+# Generated automatically from Makefile.in by configure.
+# Makefile for extras.
+#
+# Copyright © 1995,1998 by Jef Poskanzer <jef@mail.acme.com>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+BINDIR = ${exec_prefix}/sbin
+WEBDIR = $(prefix)/www
+CGIBINDIR = $(WEBDIR)/cgi-bin
+MANDIR = /usr/local/man
+
+CC = gcc
+CCOPT = -O2
+DEFS = -DHAVE__PROGNAME=1 -DHAVE_FCNTL_H=1 -DHAVE_GRP_H=1 -DHAVE_MEMORY_H=1 -DHAVE_PATHS_H=1 -DHAVE_POLL_H=1 -DHAVE_SYS_POLL_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DIRENT_H=1 -DHAVE_LIBCRYPT=1 -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_VSNPRINTF=1 -DHAVE_DAEMON=1 -DHAVE_SETSID=1 -DHAVE_GETADDRINFO=1 -DHAVE_GETNAMEINFO=1 -DHAVE_GAI_STRERROR=1 -DHAVE_SIGSET=1 -DHAVE_ATOLL=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_SELECT=1 -DHAVE_POLL=1 -DHAVE_TM_GMTOFF=1 -DHAVE_INT64T=1 -DHAVE_SOCKLENT=1
+INCLS = -I..
+CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
+STATICFLAG =
+LDFLAGS =
+LIBS = -lcrypt
+NETLIBS =
+INSTALL = /usr/bin/install -c
+
+CLEANFILES = *.o makeweb htpasswd
+
+
+
+.c.o:
+ @rm -f $@
+ $(CC) $(CFLAGS) -c $*.c
+
+all: makeweb htpasswd
+
+makeweb: makeweb.o
+ $(CC) $(LDFLAGS) makeweb.o -o makeweb $(LIBS) $(NETLIBS)
+
+makeweb.o: makeweb.c ../config.h
+ $(CC) $(CFLAGS) -DWEBDIR=\"$(WEBDIR)\" -c makeweb.c
+
+htpasswd: htpasswd.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) htpasswd.o -o htpasswd $(LIBS)
+
+htpasswd.o: htpasswd.c ../config.h
+ $(CC) $(CFLAGS) -DWEBDIR=\"$(WEBDIR)\" -c htpasswd.c
+
+
+install: all
+ rm -f $(BINDIR)/makeweb $(BINDIR)/htpasswd $(BINDIR)/syslogtocern
+ cp makeweb $(BINDIR)/makeweb
+ chgrp $(WEBGROUP) $(BINDIR)/makeweb
+ chmod 2755 $(BINDIR)/makeweb
+ cp htpasswd $(BINDIR)/htpasswd
+ cp syslogtocern $(BINDIR)/syslogtocern
+ rm -f $(MANDIR)/man1/makeweb.1
+ cp makeweb.1 $(MANDIR)/man1/makeweb.1
+ rm -f $(MANDIR)/man1/htpasswd.1
+ cp htpasswd.1 $(MANDIR)/man1/htpasswd.1
+ rm -f $(MANDIR)/man8/syslogtocern.8
+ cp syslogtocern.8 $(MANDIR)/man8/syslogtocern.8
+
+clean:
+ rm -f $(CLEANFILES)
+
+distclean:
+ rm -f $(CLEANFILES) Makefile
--- /dev/null
+# Makefile for extras.
+#
+# Copyright © 1995,1998 by Jef Poskanzer <jef@mail.acme.com>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+BINDIR = @sbindir@
+WEBDIR = $(prefix)/www
+CGIBINDIR = $(WEBDIR)/cgi-bin
+MANDIR = @mandir@
+
+CC = @CC@
+CCOPT = @V_CCOPT@
+DEFS = @DEFS@
+INCLS = -I..
+CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
+STATICFLAG = @V_STATICFLAG@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+NETLIBS = @V_NETLIBS@
+INSTALL = @INSTALL@
+
+CLEANFILES = *.o makeweb htpasswd
+
+@SET_MAKE@
+
+.c.o:
+ @rm -f $@
+ $(CC) $(CFLAGS) -c $*.c
+
+all: makeweb htpasswd
+
+makeweb: makeweb.o
+ $(CC) $(LDFLAGS) makeweb.o -o makeweb $(LIBS) $(NETLIBS)
+
+makeweb.o: makeweb.c ../config.h
+ $(CC) $(CFLAGS) -DWEBDIR=\"$(WEBDIR)\" -c makeweb.c
+
+htpasswd: htpasswd.o
+ $(CC) $(LDFLAGS) $(STATICFLAG) htpasswd.o -o htpasswd $(LIBS)
+
+htpasswd.o: htpasswd.c ../config.h
+ $(CC) $(CFLAGS) -DWEBDIR=\"$(WEBDIR)\" -c htpasswd.c
+
+
+install: all
+ rm -f $(BINDIR)/makeweb $(BINDIR)/htpasswd $(BINDIR)/syslogtocern
+ cp makeweb $(BINDIR)/makeweb
+ chgrp $(WEBGROUP) $(BINDIR)/makeweb
+ chmod 2755 $(BINDIR)/makeweb
+ cp htpasswd $(BINDIR)/htpasswd
+ cp syslogtocern $(BINDIR)/syslogtocern
+ rm -f $(MANDIR)/man1/makeweb.1
+ cp makeweb.1 $(MANDIR)/man1/makeweb.1
+ rm -f $(MANDIR)/man1/htpasswd.1
+ cp htpasswd.1 $(MANDIR)/man1/htpasswd.1
+ rm -f $(MANDIR)/man8/syslogtocern.8
+ cp syslogtocern.8 $(MANDIR)/man8/syslogtocern.8
+
+clean:
+ rm -f $(CLEANFILES)
+
+distclean:
+ rm -f $(CLEANFILES) Makefile
--- /dev/null
+.TH htpasswd 1 "05 May 1998"
+.SH NAME
+htpasswd - manipulate HTTP-server password files
+.SH SYNOPSIS
+.B htpasswd
+.RB [ -c ]
+.I passwordfile
+.I username
+.SH DESCRIPTION
+.PP
+Sets a user's password in an httpd-style password file.
+The -c flag creates a new file.
+.SH AUTHOR
+Rob McCool.
+Modified 29aug97 by Jef Poskanzer to accept new password on stdin,
+if stdin is a pipe or file. This is necessary for use from CGI.
--- /dev/null
+/*
+ * htpasswd.c: simple program for manipulating password file for NCSA httpd
+ *
+ * Rob McCool
+ */
+
+/* Modified 29aug97 by Jef Poskanzer to accept new password on stdin,
+** if stdin is a pipe or file. This is necessary for use from CGI.
+*/
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#define LF 10
+#define CR 13
+
+#define MAX_STRING_LEN 256
+
+int tfd;
+char temp_template[] = "/tmp/htp.XXXXXX";
+
+void interrupted(int);
+
+static char * strd(char *s) {
+ char *d;
+
+ d=(char *)malloc(strlen(s) + 1);
+ strcpy(d,s);
+ return(d);
+}
+
+static void getword(char *word, char *line, char stop) {
+ int x = 0,y;
+
+ for(x=0;((line[x]) && (line[x] != stop));x++)
+ word[x] = line[x];
+
+ word[x] = '\0';
+ if(line[x]) ++x;
+ y=0;
+
+ while((line[y++] = line[x++]));
+}
+
+static int my_getline(char *s, int n, FILE *f) {
+ int i=0;
+
+ while(1) {
+ s[i] = (char)fgetc(f);
+
+ if(s[i] == CR)
+ s[i] = fgetc(f);
+
+ if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
+ s[i] = '\0';
+ return (feof(f) ? 1 : 0);
+ }
+ ++i;
+ }
+}
+
+static void putline(FILE *f,char *l) {
+ int x;
+
+ for(x=0;l[x];x++) fputc(l[x],f);
+ fputc('\n',f);
+}
+
+
+/* From local_passwd.c (C) Regents of Univ. of California blah blah */
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void to64(char *s, long v, int n) {
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+#ifdef MPE
+/* MPE lacks getpass() and a way to suppress stdin echo. So for now, just
+issue the prompt and read the results with echo. (Ugh). */
+
+char *getpass(const char *prompt) {
+
+static char password[81];
+
+fputs(prompt,stderr);
+gets((char *)&password);
+
+if (strlen((char *)&password) > 8) {
+ password[8]='\0';
+}
+
+return (char *)&password;
+}
+#endif
+
+static void
+add_password( char* user, FILE* f )
+ {
+ char pass[100];
+ char* pw;
+ char* cpw;
+ char salt[3];
+
+ if ( ! isatty( fileno( stdin ) ) )
+ {
+ (void) fgets( pass, sizeof(pass), stdin );
+ if ( pass[strlen(pass) - 1] == '\n' )
+ pass[strlen(pass) - 1] = '\0';
+ pw = pass;
+ }
+ else
+ {
+ pw = strd( (char*) getpass( "New password:" ) );
+ if ( strcmp( pw, (char*) getpass( "Re-type new password:" ) ) != 0 )
+ {
+ (void) fprintf( stderr, "They don't match, sorry.\n" );
+ if ( tfd != -1 )
+ unlink( temp_template );
+ exit( 1 );
+ }
+ }
+ (void) srandom( (int) time( (time_t*) 0 ) );
+ to64( &salt[0], random(), 2 );
+ cpw = crypt( pw, salt );
+ (void) fprintf( f, "%s:%s\n", user, cpw );
+ }
+
+static void usage(void) {
+ fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n");
+ fprintf(stderr,"The -c flag creates a new file.\n");
+ exit(1);
+}
+
+void interrupted(int signo) {
+ fprintf(stderr,"Interrupted.\n");
+ if(tfd != -1) unlink(temp_template);
+ exit(1);
+}
+
+int main(int argc, char *argv[]) {
+ FILE *tfp,*f;
+ char user[MAX_STRING_LEN];
+ char line[MAX_STRING_LEN];
+ char l[MAX_STRING_LEN];
+ char w[MAX_STRING_LEN];
+ char command[MAX_STRING_LEN];
+ int found;
+
+ tfd = -1;
+ signal(SIGINT,(void (*)(int))interrupted);
+ if(argc == 4) {
+ if(strcmp(argv[1],"-c"))
+ usage();
+ if(!(tfp = fopen(argv[2],"w"))) {
+ fprintf(stderr,"Could not open passwd file %s for writing.\n",
+ argv[2]);
+ perror("fopen");
+ exit(1);
+ }
+ printf("Adding password for %s.\n",argv[3]);
+ add_password(argv[3],tfp);
+ fclose(tfp);
+ exit(0);
+ } else if(argc != 3) usage();
+
+ tfd = mkstemp(temp_template);
+ if(!(tfp = fdopen(tfd,"w"))) {
+ fprintf(stderr,"Could not open temp file.\n");
+ exit(1);
+ }
+
+ if(!(f = fopen(argv[1],"r"))) {
+ fprintf(stderr,
+ "Could not open passwd file %s for reading.\n",argv[1]);
+ fprintf(stderr,"Use -c option to create new one.\n");
+ exit(1);
+ }
+ strncpy(user,argv[2],sizeof(user)-1);
+ user[sizeof(user)-1] = '\0';
+
+ found = 0;
+ while(!(my_getline(line,MAX_STRING_LEN,f))) {
+ if(found || (line[0] == '#') || (!line[0])) {
+ putline(tfp,line);
+ continue;
+ }
+ strcpy(l,line);
+ getword(w,l,':');
+ if(strcmp(user,w)) {
+ putline(tfp,line);
+ continue;
+ }
+ else {
+ printf("Changing password for user %s\n",user);
+ add_password(user,tfp);
+ found = 1;
+ }
+ }
+ if(!found) {
+ printf("Adding user %s\n",user);
+ add_password(user,tfp);
+ }
+ fclose(f);
+ fclose(tfp);
+ sprintf(command,"cp %s %s",temp_template,argv[1]);
+ system(command);
+ unlink(temp_template);
+ exit(0);
+}
--- /dev/null
+.TH makeweb 1 "06 September 1995"
+.SH NAME
+makeweb - create user web directory
+.SH SYNOPSIS
+.B makeweb
+.SH DESCRIPTION
+.PP
+This program allows users to create their own web subdirectories off
+of the main web directory.
+.SH "SEE ALSO
+thttpd(8)
+.SH AUTHOR
+Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+All rights reserved.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
--- /dev/null
+/* makeweb.c - let a user create a web subdirectory
+**
+** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+/* This is intended to be installed setgid to a group that has
+** write access to the system web directory. It allows any user
+** to create a subdirectory there. It also makes a symbolic link
+** in the user's home directory pointing at the new web subdir.
+*/
+
+
+#include "../config.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#define LINK "public_html"
+
+static char* argv0;
+
+
+static void
+check_room( int size, int len )
+ {
+ if ( len > size )
+ {
+ (void) fprintf( stderr, "%s: internal error, out of room\n", argv0 );
+ exit( 1 );
+ }
+ }
+
+
+static void
+end_with_slash( char* str )
+ {
+ if ( str[strlen( str ) - 1] != '/' )
+ (void) strcat( str, "/" );
+ }
+
+
+static void
+check_dir( char* dirname, uid_t uid, gid_t gid )
+ {
+ struct stat sb;
+
+ /* Check the directory. */
+ if ( stat( dirname, &sb ) < 0 )
+ {
+ if ( errno != ENOENT )
+ {
+ perror( dirname );
+ exit( 1 );
+ }
+ /* Doesn't exist. Try to make it. */
+ if ( mkdir( dirname, 0755 ) < 0 )
+ {
+ if ( errno == ENOENT )
+ (void) printf( "\
+Some part of the path %s does not exist.\n\
+This is probably a configuration error.\n", dirname );
+ else
+ perror( dirname );
+ exit( 1 );
+ }
+ (void) printf( "Created web directory %s\n", dirname );
+ /* Try to change the group of the new dir to the user's group. */
+ (void) chown( dirname, -1, gid );
+ }
+ else
+ {
+ /* The directory already exists. Well, check that it is in
+ ** fact a directory.
+ */
+ if ( ! S_ISDIR( sb.st_mode ) )
+ {
+ (void) printf(
+ "%s already exists but is not a directory!\n", dirname );
+ exit( 1 );
+ }
+ if ( sb.st_uid != uid )
+ {
+ (void) printf(
+ "%s already exists but you don't own it!\n", dirname );
+ exit( 1 );
+ }
+ (void) printf( "Web directory %s already existed.\n", dirname );
+ }
+ }
+
+
+int
+main( int argc, char** argv )
+ {
+ char* webdir;
+ char* prefix;
+ struct passwd* pwd;
+ char* username;
+ char* homedir;
+ char dirname[5000];
+ char linkname[5000];
+ char linkbuf[5000];
+ struct stat sb;
+
+ argv0 = argv[0];
+ if ( argc != 1 )
+ {
+ (void) fprintf( stderr, "usage: %s\n", argv0 );
+ exit( 1 );
+ }
+
+ pwd = getpwuid( getuid() );
+ if ( pwd == (struct passwd*) 0 )
+ {
+ (void) fprintf( stderr, "%s: can't find your username\n", argv0 );
+ exit( 1 );
+ }
+ username = pwd->pw_name;
+ homedir = pwd->pw_dir;
+
+#ifdef TILDE_MAP_2
+
+ /* All we have to do for the TILDE_MAP_2 case is make sure there's
+ ** a public_html subdirectory.
+ */
+ check_room(
+ sizeof(dirname), strlen( homedir ) + strlen( TILDE_MAP_2 ) + 2 );
+ (void) strcpy( dirname, homedir );
+ end_with_slash( dirname );
+ (void) strcat( dirname, TILDE_MAP_2 );
+
+ check_dir( dirname, pwd->pw_uid, pwd->pw_gid );
+
+#else /* TILDE_MAP_2 */
+
+ /* Gather the pieces. */
+ webdir = WEBDIR;
+#ifdef TILDE_MAP_1
+ prefix = TILDE_MAP_1;
+#else /* TILDE_MAP_1 */
+ prefix = "";
+#endif /* TILDE_MAP_1 */
+
+ /* Assemble the directory name. Be paranoid cause we're sgid. */
+ check_room(
+ sizeof(dirname),
+ strlen( webdir ) + strlen( prefix ) + strlen( username ) + 3 );
+ (void) strcpy( dirname, webdir );
+ end_with_slash( dirname );
+ if ( strlen( prefix ) != 0 )
+ {
+ (void) strcat( dirname, prefix );
+ end_with_slash( dirname );
+ }
+ (void) strcat( dirname, username );
+
+ /* Assemble the link name. */
+ check_room( sizeof(linkname), strlen( homedir ) + strlen( LINK ) + 2 );
+ (void) strcpy( linkname, homedir );
+ end_with_slash( linkname );
+ (void) strcat( linkname, LINK );
+
+ check_dir( dirname, pwd->pw_uid, pwd->pw_gid );
+
+ /* Check the symlink. */
+ try_link_again: ;
+ if ( lstat( linkname, &sb ) < 0 )
+ {
+ if ( errno != ENOENT )
+ {
+ perror( linkname );
+ exit( 1 );
+ }
+ /* Doesn't exist. Try to make it. */
+ if ( symlink( dirname, linkname ) < 0 )
+ {
+ if ( errno == ENOENT )
+ (void) printf( "\
+Some part of the path %s does not exist.\n\
+This is probably a configuration error.\n", linkname );
+ else
+ perror( linkname );
+ exit( 1 );
+ }
+ (void) printf( "Created symbolic link %s\n", linkname );
+ }
+ else
+ {
+ /* The link already exists. Well, check that it is in
+ ** fact a link.
+ */
+ if ( ! S_ISLNK( sb.st_mode ) )
+ {
+ (void) printf( "\
+%s already exists but is not a\n\
+symbolic link! Perhaps you have a real web subdirectory in your\n\
+home dir from a previous web server configuration? You may have\n\
+to rename it, run %s again, and then copy in the old\n\
+contents.\n", linkname, argv0 );
+ exit( 1 );
+ }
+ /* Check the existing link's contents. */
+ if ( readlink( linkname, linkbuf, sizeof(linkbuf) ) < 0 )
+ {
+ perror( linkname );
+ exit( 1 );
+ }
+ if ( strcmp( dirname, linkbuf ) == 0 )
+ (void) printf( "Symbolic link %s already existed.\n", linkname );
+ else
+ {
+ (void) printf( "\
+Symbolic link %s already existed\n\
+but it points to the wrong place! Attempting to remove and\n\
+recreate it.\n", linkname );
+ if ( unlink( linkname ) < 0 )
+ {
+ perror( linkname );
+ exit( 1 );
+ }
+ goto try_link_again;
+ }
+ }
+#endif /* TILDE_MAP_2 */
+
+ exit( 0 );
+ }
--- /dev/null
+#!/bin/sh
+#
+# syslogtocern - convert thttpd syslog entries into CERN Combined Log Format
+#
+# Copyright © 1995,1998 by Jef Poskanzer <jef@mail.acme.com>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+if [ $# -lt 1 ] ; then
+ echo "usage: $0 logfile ..." >&2
+ exit 1
+fi
+
+tmp1=/tmp/stc1.$$
+rm -f $tmp1
+
+# Gather up all the thttpd entries.
+egrep -h ' thttpd\[' "$@" > $tmp1
+
+# Figure out the current year - it's not in syslog's output. Some versions
+# of date have the %Y directive to give the full four-digit year, but others
+# only have %y.
+year=`date +%y`
+if [ $year -gt 70 ] ; then
+ year=19$year
+else
+ year=20$year
+fi
+
+# If the current year isn't the year that the logfile was generated, we need
+# to fix it. This will most likely happen once a year, when this script is
+# run on January 1st for December 31st's logfile. So, if the current month
+# is January and there are December dates in the log file, we subtract one.
+# This should cover most cases.
+if [ `date +%m` -eq 1 -a `head -1 $tmp1 | awk '{print $1}'` = "Dec" ] ; then
+ year=`echo $year - 1 | bc`
+fi
+
+# Do access_log.
+awk < $tmp1 '{if ( NF >= 15 && $7 == "-" && $12 >= 100 && $12 < 510) print;}' |
+ sed -e "s,\([A-Z][a-z][a-z]\) \([0-9 ][0-9]\) \([0-9][0-9]:[0-9][0-9]:[0-9][0-9]\) [^ ]* thttpd\[[0-9]*\]: \([^ ]* [^ ]* [^ ]*\) \(.*\),\4 [\2/\1/${year}:\3] \5," -e 's,\[ ,[0,' > access_log
+
+# Do error_log.
+awk < $tmp1 '{if ( ! ( NF >= 15 && $7 == "-" && $12 >= 100 && $12 < 510) ) print;}' |
+ sed -e "s,\([A-Z][a-z][a-z] [0-9 ][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\) [^ ]* thttpd\[[0-9]*\]: \(.*\),[\1 ${year}] \2," > error_log
+
+# Done.
+rm -f $tmp1
--- /dev/null
+.TH syslogtocern 8 "12 October 1995"
+.SH NAME
+syslogtocern - convert thttpd syslog entries into CERN Common Log format
+.SH SYNOPSIS
+.B syslogtocern
+.I logfile
+.RI ...
+.SH DESCRIPTION
+.PP
+Reads one or more syslog files as input.
+Takes the thttpd entries, and converts them into CERN Combined Common
+Log format.
+Produces two files as output: access_log and error_log.
+If files with those names already exist in the current directory, they
+are overwritten.
+.SH "SEE ALSO"
+thttpd(8)
+.SH "BUGS / DEFICIENCIES"
+Lumps all thttpd processes together.
+It ought to produce separate files for each, identified by IP address and
+port number.
+However, that change represents a huge increase in complexity, so next version.
+.SH AUTHOR
+Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+All rights reserved.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
--- /dev/null
+/* fdwatch.c - fd watcher routines, either select() or poll()
+**
+** Copyright © 1999,2000 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <syslog.h>
+#include <fcntl.h>
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else /* HAVE_POLL_H */
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif /* HAVE_SYS_POLL_H */
+#endif /* HAVE_POLL_H */
+
+#ifdef HAVE_SYS_DEVPOLL_H
+#include <sys/devpoll.h>
+#ifndef HAVE_DEVPOLL
+#define HAVE_DEVPOLL
+#endif /* !HAVE_DEVPOLL */
+#endif /* HAVE_SYS_DEVPOLL_H */
+
+#ifdef HAVE_SYS_EVENT_H
+#include <sys/event.h>
+#endif /* HAVE_SYS_EVENT_H */
+
+#include "fdwatch.h"
+
+#ifdef HAVE_SELECT
+#ifndef FD_SET
+#define NFDBITS 32
+#define FD_SETSIZE 32
+#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p) bzero((char*)(p), sizeof(*(p)))
+#endif /* !FD_SET */
+#endif /* HAVE_SELECT */
+
+static int nfiles;
+static long nwatches;
+static int* fd_rw;
+static void** fd_data;
+static int nreturned, next_ridx;
+
+#ifdef HAVE_KQUEUE
+
+#define WHICH "kevent"
+#define INIT( nf ) kqueue_init( nf )
+#define ADD_FD( fd, rw ) kqueue_add_fd( fd, rw )
+#define DEL_FD( fd ) kqueue_del_fd( fd )
+#define WATCH( timeout_msecs ) kqueue_watch( timeout_msecs )
+#define CHECK_FD( fd ) kqueue_check_fd( fd )
+#define GET_FD( ridx ) kqueue_get_fd( ridx )
+
+static int kqueue_init( int nf );
+static void kqueue_add_fd( int fd, int rw );
+static void kqueue_del_fd( int fd );
+static int kqueue_watch( long timeout_msecs );
+static int kqueue_check_fd( int fd );
+static int kqueue_get_fd( int ridx );
+
+#else /* HAVE_KQUEUE */
+# ifdef HAVE_DEVPOLL
+
+#define WHICH "devpoll"
+#define INIT( nf ) devpoll_init( nf )
+#define ADD_FD( fd, rw ) devpoll_add_fd( fd, rw )
+#define DEL_FD( fd ) devpoll_del_fd( fd )
+#define WATCH( timeout_msecs ) devpoll_watch( timeout_msecs )
+#define CHECK_FD( fd ) devpoll_check_fd( fd )
+#define GET_FD( ridx ) devpoll_get_fd( ridx )
+
+static int devpoll_init( int nf );
+static void devpoll_add_fd( int fd, int rw );
+static void devpoll_del_fd( int fd );
+static int devpoll_watch( long timeout_msecs );
+static int devpoll_check_fd( int fd );
+static int devpoll_get_fd( int ridx );
+
+# else /* HAVE_DEVPOLL */
+# ifdef HAVE_POLL
+
+#define WHICH "poll"
+#define INIT( nf ) poll_init( nf )
+#define ADD_FD( fd, rw ) poll_add_fd( fd, rw )
+#define DEL_FD( fd ) poll_del_fd( fd )
+#define WATCH( timeout_msecs ) poll_watch( timeout_msecs )
+#define CHECK_FD( fd ) poll_check_fd( fd )
+#define GET_FD( ridx ) poll_get_fd( ridx )
+
+static int poll_init( int nf );
+static void poll_add_fd( int fd, int rw );
+static void poll_del_fd( int fd );
+static int poll_watch( long timeout_msecs );
+static int poll_check_fd( int fd );
+static int poll_get_fd( int ridx );
+
+# else /* HAVE_POLL */
+# ifdef HAVE_SELECT
+
+#define WHICH "select"
+#define INIT( nf ) select_init( nf )
+#define ADD_FD( fd, rw ) select_add_fd( fd, rw )
+#define DEL_FD( fd ) select_del_fd( fd )
+#define WATCH( timeout_msecs ) select_watch( timeout_msecs )
+#define CHECK_FD( fd ) select_check_fd( fd )
+#define GET_FD( ridx ) select_get_fd( ridx )
+
+static int select_init( int nf );
+static void select_add_fd( int fd, int rw );
+static void select_del_fd( int fd );
+static int select_watch( long timeout_msecs );
+static int select_check_fd( int fd );
+static int select_get_fd( int ridx );
+
+# endif /* HAVE_SELECT */
+# endif /* HAVE_POLL */
+# endif /* HAVE_DEVPOLL */
+#endif /* HAVE_KQUEUE */
+
+
+/* Routines. */
+
+/* Figure out how many file descriptors the system allows, and
+** initialize the fdwatch data structures. Returns -1 on failure.
+*/
+int
+fdwatch_get_nfiles( void )
+ {
+ int i;
+#ifdef RLIMIT_NOFILE
+ struct rlimit rl;
+#endif /* RLIMIT_NOFILE */
+
+ /* Figure out how many fd's we can have. */
+ nfiles = getdtablesize();
+#ifdef RLIMIT_NOFILE
+ /* If we have getrlimit(), use that, and attempt to raise the limit. */
+ if ( getrlimit( RLIMIT_NOFILE, &rl ) == 0 )
+ {
+ nfiles = rl.rlim_cur;
+ if ( rl.rlim_max == RLIM_INFINITY )
+ rl.rlim_cur = 8192; /* arbitrary */
+ else if ( rl.rlim_max > rl.rlim_cur )
+ rl.rlim_cur = rl.rlim_max;
+ if ( setrlimit( RLIMIT_NOFILE, &rl ) == 0 )
+ nfiles = rl.rlim_cur;
+ }
+#endif /* RLIMIT_NOFILE */
+
+#if defined(HAVE_SELECT) && ! ( defined(HAVE_POLL) || defined(HAVE_DEVPOLL) || defined(HAVE_KQUEUE) )
+ /* If we use select(), then we must limit ourselves to FD_SETSIZE. */
+ nfiles = MIN( nfiles, FD_SETSIZE );
+#endif /* HAVE_SELECT && ! ( HAVE_POLL || HAVE_DEVPOLL || HAVE_KQUEUE ) */
+
+ /* Initialize the fdwatch data structures. */
+ nwatches = 0;
+ fd_rw = (int*) malloc( sizeof(int) * nfiles );
+ fd_data = (void**) malloc( sizeof(void*) * nfiles );
+ if ( fd_rw == (int*) 0 || fd_data == (void**) 0 )
+ return -1;
+ for ( i = 0; i < nfiles; ++i )
+ fd_rw[i] = -1;
+ if ( INIT( nfiles ) == -1 )
+ return -1;
+
+ return nfiles;
+ }
+
+
+/* Add a descriptor to the watch list. rw is either FDW_READ or FDW_WRITE. */
+void
+fdwatch_add_fd( int fd, void* client_data, int rw )
+ {
+ if ( fd < 0 || fd >= nfiles || fd_rw[fd] != -1 )
+ {
+ syslog( LOG_ERR, "bad fd (%d) passed to fdwatch_add_fd!", fd );
+ return;
+ }
+ ADD_FD( fd, rw );
+ fd_rw[fd] = rw;
+ fd_data[fd] = client_data;
+ }
+
+
+/* Remove a descriptor from the watch list. */
+void
+fdwatch_del_fd( int fd )
+ {
+ if ( fd < 0 || fd >= nfiles || fd_rw[fd] == -1 )
+ {
+ syslog( LOG_ERR, "bad fd (%d) passed to fdwatch_del_fd!", fd );
+ return;
+ }
+ DEL_FD( fd );
+ fd_rw[fd] = -1;
+ fd_data[fd] = (void*) 0;
+ }
+
+/* Do the watch. Return value is the number of descriptors that are ready,
+** or 0 if the timeout expired, or -1 on errors. A timeout of INFTIM means
+** wait indefinitely.
+*/
+int
+fdwatch( long timeout_msecs )
+ {
+ ++nwatches;
+ nreturned = WATCH( timeout_msecs );
+ next_ridx = 0;
+ return nreturned;
+ }
+
+
+/* Check if a descriptor was ready. */
+int
+fdwatch_check_fd( int fd )
+ {
+ if ( fd < 0 || fd >= nfiles || fd_rw[fd] == -1 )
+ {
+ syslog( LOG_ERR, "bad fd (%d) passed to fdwatch_check_fd!", fd );
+ return 0;
+ }
+ return CHECK_FD( fd );
+ }
+
+
+void*
+fdwatch_get_next_client_data( void )
+ {
+ int fd;
+
+ if ( next_ridx >= nreturned )
+ return (void*) -1;
+ fd = GET_FD( next_ridx++ );
+ if ( fd < 0 || fd >= nfiles )
+ return (void*) 0;
+ return fd_data[fd];
+ }
+
+
+/* Generate debugging statistics syslog message. */
+void
+fdwatch_logstats( long secs )
+ {
+ if ( secs > 0 )
+ syslog(
+ LOG_NOTICE, " fdwatch - %ld %ss (%g/sec)",
+ nwatches, WHICH, (float) nwatches / secs );
+ nwatches = 0;
+ }
+
+
+#ifdef HAVE_KQUEUE
+
+static int maxkqevents;
+static struct kevent* kqevents;
+static int nkqevents;
+static struct kevent* kqrevents;
+static int* kqrfdidx;
+static int kq;
+
+
+static int
+kqueue_init( int nf )
+ {
+ kq = kqueue();
+ if ( kq == -1 )
+ return -1;
+ maxkqevents = nf * 2;
+ kqevents = (struct kevent*) malloc( sizeof(struct kevent) * maxkqevents );
+ kqrevents = (struct kevent*) malloc( sizeof(struct kevent) * nf );
+ kqrfdidx = (int*) malloc( sizeof(int) * nf );
+ if ( kqevents == (struct kevent*) 0 || kqrevents == (struct kevent*) 0 ||
+ kqrfdidx == (int*) 0 )
+ return -1;
+ (void) memset( kqevents, 0, sizeof(struct kevent) * maxkqevents );
+ (void) memset( kqrfdidx, 0, sizeof(int) * nf );
+ return 0;
+ }
+
+
+static void
+kqueue_add_fd( int fd, int rw )
+ {
+ if ( nkqevents >= maxkqevents )
+ {
+ syslog( LOG_ERR, "too many kqevents in kqueue_add_fd!" );
+ return;
+ }
+ kqevents[nkqevents].ident = fd;
+ kqevents[nkqevents].flags = EV_ADD;
+ switch ( rw )
+ {
+ case FDW_READ: kqevents[nkqevents].filter = EVFILT_READ; break;
+ case FDW_WRITE: kqevents[nkqevents].filter = EVFILT_WRITE; break;
+ default: break;
+ }
+ ++nkqevents;
+ }
+
+
+static void
+kqueue_del_fd( int fd )
+ {
+ if ( nkqevents >= maxkqevents )
+ {
+ syslog( LOG_ERR, "too many kqevents in kqueue_del_fd!" );
+ return;
+ }
+ kqevents[nkqevents].ident = fd;
+ kqevents[nkqevents].flags = EV_DELETE;
+ switch ( fd_rw[fd] )
+ {
+ case FDW_READ: kqevents[nkqevents].filter = EVFILT_READ; break;
+ case FDW_WRITE: kqevents[nkqevents].filter = EVFILT_WRITE; break;
+ }
+ ++nkqevents;
+ }
+
+
+static int
+kqueue_watch( long timeout_msecs )
+ {
+ int i, r;
+
+ if ( timeout_msecs == INFTIM )
+ r = kevent(
+ kq, kqevents, nkqevents, kqrevents, nfiles, (struct timespec*) 0 );
+ else
+ {
+ struct timespec ts;
+ ts.tv_sec = timeout_msecs / 1000L;
+ ts.tv_nsec = ( timeout_msecs % 1000L ) * 1000000L;
+ r = kevent( kq, kqevents, nkqevents, kqrevents, nfiles, &ts );
+ }
+ nkqevents = 0;
+ if ( r == -1 )
+ return -1;
+
+ for ( i = 0; i < r; ++i )
+ kqrfdidx[kqrevents[i].ident] = i;
+
+ return r;
+ }
+
+
+static int
+kqueue_check_fd( int fd )
+ {
+ int ridx = kqrfdidx[fd];
+
+ if ( ridx < 0 || ridx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad ridx (%d) in kqueue_check_fd!", ridx );
+ return 0;
+ }
+ if ( ridx >= nreturned )
+ return 0;
+ if ( kqrevents[ridx].ident != fd )
+ return 0;
+ if ( kqrevents[ridx].flags & EV_ERROR )
+ return 0;
+ switch ( fd_rw[fd] )
+ {
+ case FDW_READ: return kqrevents[ridx].filter == EVFILT_READ;
+ case FDW_WRITE: return kqrevents[ridx].filter == EVFILT_WRITE;
+ default: return 0;
+ }
+ }
+
+
+static int
+kqueue_get_fd( int ridx )
+ {
+ if ( ridx < 0 || ridx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad ridx (%d) in kqueue_get_fd!", ridx );
+ return -1;
+ }
+ return kqrevents[ridx].ident;
+ }
+
+#else /* HAVE_KQUEUE */
+
+
+# ifdef HAVE_DEVPOLL
+
+static int maxdpevents;
+static struct pollfd* dpevents;
+static int ndpevents;
+static struct pollfd* dprevents;
+static int* dp_rfdidx;
+static int dp;
+
+
+static int
+devpoll_init( int nf )
+ {
+ dp = open( "/dev/poll", O_RDWR );
+ if ( dp == -1 )
+ return -1;
+ (void) fcntl( dp, F_SETFD, 1 );
+ maxdpevents = nf * 2;
+ dpevents = (struct pollfd*) malloc( sizeof(struct pollfd) * maxdpevents );
+ dprevents = (struct pollfd*) malloc( sizeof(struct pollfd) * nf );
+ dp_rfdidx = (int*) malloc( sizeof(int) * nf );
+ if ( dpevents == (struct pollfd*) 0 || dprevents == (struct pollfd*) 0 ||
+ dp_rfdidx == (int*) 0 )
+ return -1;
+ (void) memset( dp_rfdidx, 0, sizeof(int) * nf );
+ return 0;
+ }
+
+
+static void
+devpoll_add_fd( int fd, int rw )
+ {
+ if ( ndpevents >= maxdpevents )
+ {
+ syslog( LOG_ERR, "too many fds in devpoll_add_fd!" );
+ return;
+ }
+ dpevents[ndpevents].fd = fd;
+ switch ( rw )
+ {
+ case FDW_READ: dpevents[ndpevents].events = POLLIN; break;
+ case FDW_WRITE: dpevents[ndpevents].events = POLLOUT; break;
+ default: break;
+ }
+ ++ndpevents;
+ }
+
+
+static void
+devpoll_del_fd( int fd )
+ {
+ if ( ndpevents >= maxdpevents )
+ {
+ syslog( LOG_ERR, "too many fds in devpoll_del_fd!" );
+ return;
+ }
+ dpevents[ndpevents].fd = fd;
+ dpevents[ndpevents].events = POLLREMOVE;
+ ++ndpevents;
+ }
+
+
+static int
+devpoll_watch( long timeout_msecs )
+ {
+ int i, r;
+ struct dvpoll dvp;
+
+ r = sizeof(struct pollfd) * ndpevents;
+ if ( r > 0 && write( dp, dpevents, r ) != r )
+ return -1;
+
+ ndpevents = 0;
+ dvp.dp_fds = dprevents;
+ dvp.dp_nfds = nfiles;
+ dvp.dp_timeout = (int) timeout_msecs;
+
+ r = ioctl( dp, DP_POLL, &dvp );
+ if ( r == -1 )
+ return -1;
+
+ for ( i = 0; i < r; ++i )
+ dp_rfdidx[dprevents[i].fd] = i;
+
+ return r;
+ }
+
+
+static int
+devpoll_check_fd( int fd )
+ {
+ int ridx = dp_rfdidx[fd];
+
+ if ( ridx < 0 || ridx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad ridx (%d) in devpoll_check_fd!", ridx );
+ return 0;
+ }
+ if ( ridx >= nreturned )
+ return 0;
+ if ( dprevents[ridx].fd != fd )
+ return 0;
+ if ( dprevents[ridx].revents & POLLERR )
+ return 0;
+ switch ( fd_rw[fd] )
+ {
+ case FDW_READ: return dprevents[ridx].revents & ( POLLIN | POLLHUP | POLLNVAL );
+ case FDW_WRITE: return dprevents[ridx].revents & ( POLLOUT | POLLHUP | POLLNVAL );
+ default: return 0;
+ }
+ }
+
+
+static int
+devpoll_get_fd( int ridx )
+ {
+ if ( ridx < 0 || ridx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad ridx (%d) in devpoll_get_fd!", ridx );
+ return -1;
+ }
+ return dprevents[ridx].fd;
+ }
+
+
+# else /* HAVE_DEVPOLL */
+
+
+# ifdef HAVE_POLL
+
+static struct pollfd* pollfds;
+static int npoll_fds;
+static int* poll_fdidx;
+static int* poll_rfdidx;
+
+
+static int
+poll_init( int nf )
+ {
+ int i;
+
+ pollfds = (struct pollfd*) malloc( sizeof(struct pollfd) * nf );
+ poll_fdidx = (int*) malloc( sizeof(int) * nf );
+ poll_rfdidx = (int*) malloc( sizeof(int) * nf );
+ if ( pollfds == (struct pollfd*) 0 || poll_fdidx == (int*) 0 ||
+ poll_rfdidx == (int*) 0 )
+ return -1;
+ for ( i = 0; i < nf; ++i )
+ pollfds[i].fd = poll_fdidx[i] = -1;
+ return 0;
+ }
+
+
+static void
+poll_add_fd( int fd, int rw )
+ {
+ if ( npoll_fds >= nfiles )
+ {
+ syslog( LOG_ERR, "too many fds in poll_add_fd!" );
+ return;
+ }
+ pollfds[npoll_fds].fd = fd;
+ switch ( rw )
+ {
+ case FDW_READ: pollfds[npoll_fds].events = POLLIN; break;
+ case FDW_WRITE: pollfds[npoll_fds].events = POLLOUT; break;
+ default: break;
+ }
+ poll_fdidx[fd] = npoll_fds;
+ ++npoll_fds;
+ }
+
+
+static void
+poll_del_fd( int fd )
+ {
+ int idx = poll_fdidx[fd];
+
+ if ( idx < 0 || idx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad idx (%d) in poll_del_fd!", idx );
+ return;
+ }
+ --npoll_fds;
+ pollfds[idx] = pollfds[npoll_fds];
+ poll_fdidx[pollfds[idx].fd] = idx;
+ pollfds[npoll_fds].fd = -1;
+ poll_fdidx[fd] = -1;
+ }
+
+
+static int
+poll_watch( long timeout_msecs )
+ {
+ int r, ridx, i;
+
+ r = poll( pollfds, npoll_fds, (int) timeout_msecs );
+ if ( r <= 0 )
+ return r;
+
+ ridx = 0;
+ for ( i = 0; i < npoll_fds; ++i )
+ if ( pollfds[i].revents &
+ ( POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL ) )
+ {
+ poll_rfdidx[ridx++] = pollfds[i].fd;
+ if ( ridx == r )
+ break;
+ }
+
+ return ridx; /* should be equal to r */
+ }
+
+
+static int
+poll_check_fd( int fd )
+ {
+ int fdidx = poll_fdidx[fd];
+
+ if ( fdidx < 0 || fdidx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad fdidx (%d) in poll_check_fd!", fdidx );
+ return 0;
+ }
+ if ( pollfds[fdidx].revents & POLLERR )
+ return 0;
+ switch ( fd_rw[fd] )
+ {
+ case FDW_READ: return pollfds[fdidx].revents & ( POLLIN | POLLHUP | POLLNVAL );
+ case FDW_WRITE: return pollfds[fdidx].revents & ( POLLOUT | POLLHUP | POLLNVAL );
+ default: return 0;
+ }
+ }
+
+
+static int
+poll_get_fd( int ridx )
+ {
+ if ( ridx < 0 || ridx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad ridx (%d) in poll_get_fd!", ridx );
+ return -1;
+ }
+ return poll_rfdidx[ridx];
+ }
+
+# else /* HAVE_POLL */
+
+
+# ifdef HAVE_SELECT
+
+static fd_set master_rfdset;
+static fd_set master_wfdset;
+static fd_set working_rfdset;
+static fd_set working_wfdset;
+static int* select_fds;
+static int* select_fdidx;
+static int* select_rfdidx;
+static int nselect_fds;
+static int maxfd;
+static int maxfd_changed;
+
+
+static int
+select_init( int nf )
+ {
+ int i;
+
+ FD_ZERO( &master_rfdset );
+ FD_ZERO( &master_wfdset );
+ select_fds = (int*) malloc( sizeof(int) * nf );
+ select_fdidx = (int*) malloc( sizeof(int) * nf );
+ select_rfdidx = (int*) malloc( sizeof(int) * nf );
+ if ( select_fds == (int*) 0 || select_fdidx == (int*) 0 ||
+ select_rfdidx == (int*) 0 )
+ return -1;
+ nselect_fds = 0;
+ maxfd = -1;
+ maxfd_changed = 0;
+ for ( i = 0; i < nf; ++i )
+ select_fds[i] = select_fdidx[i] = -1;
+ return 0;
+ }
+
+
+static void
+select_add_fd( int fd, int rw )
+ {
+ if ( nselect_fds >= nfiles )
+ {
+ syslog( LOG_ERR, "too many fds in select_add_fd!" );
+ return;
+ }
+ select_fds[nselect_fds] = fd;
+ switch ( rw )
+ {
+ case FDW_READ: FD_SET( fd, &master_rfdset ); break;
+ case FDW_WRITE: FD_SET( fd, &master_wfdset ); break;
+ default: break;
+ }
+ if ( fd > maxfd )
+ maxfd = fd;
+ select_fdidx[fd] = nselect_fds;
+ ++nselect_fds;
+ }
+
+
+static void
+select_del_fd( int fd )
+ {
+ int idx = select_fdidx[fd];
+
+ if ( idx < 0 || idx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad idx (%d) in select_del_fd!", idx );
+ return;
+ }
+
+ --nselect_fds;
+ select_fds[idx] = select_fds[nselect_fds];
+ select_fdidx[select_fds[idx]] = idx;
+ select_fds[nselect_fds] = -1;
+ select_fdidx[fd] = -1;
+
+ FD_CLR( fd, &master_rfdset );
+ FD_CLR( fd, &master_wfdset );
+
+ if ( fd >= maxfd )
+ maxfd_changed = 1;
+ }
+
+
+static int
+select_get_maxfd( void )
+ {
+ if ( maxfd_changed )
+ {
+ int i;
+ maxfd = -1;
+ for ( i = 0; i < nselect_fds; ++i )
+ if ( select_fds[i] > maxfd )
+ maxfd = select_fds[i];
+ maxfd_changed = 0;
+ }
+ return maxfd;
+ }
+
+
+static int
+select_watch( long timeout_msecs )
+ {
+ int mfd;
+ int r, idx, ridx;
+
+ working_rfdset = master_rfdset;
+ working_wfdset = master_wfdset;
+ mfd = select_get_maxfd();
+ if ( timeout_msecs == INFTIM )
+ r = select(
+ mfd + 1, &working_rfdset, &working_wfdset, (fd_set*) 0,
+ (struct timeval*) 0 );
+ else
+ {
+ struct timeval timeout;
+ timeout.tv_sec = timeout_msecs / 1000L;
+ timeout.tv_usec = ( timeout_msecs % 1000L ) * 1000L;
+ r = select(
+ mfd + 1, &working_rfdset, &working_wfdset, (fd_set*) 0, &timeout );
+ }
+ if ( r <= 0 )
+ return r;
+
+ ridx = 0;
+ for ( idx = 0; idx < nselect_fds; ++idx )
+ if ( select_check_fd( select_fds[idx] ) )
+ {
+ select_rfdidx[ridx++] = select_fds[idx];
+ if ( ridx == r )
+ break;
+ }
+
+ return ridx; /* should be equal to r */
+ }
+
+
+static int
+select_check_fd( int fd )
+ {
+ switch ( fd_rw[fd] )
+ {
+ case FDW_READ: return FD_ISSET( fd, &working_rfdset );
+ case FDW_WRITE: return FD_ISSET( fd, &working_wfdset );
+ default: return 0;
+ }
+ }
+
+
+static int
+select_get_fd( int ridx )
+ {
+ if ( ridx < 0 || ridx >= nfiles )
+ {
+ syslog( LOG_ERR, "bad ridx (%d) in select_get_fd!", ridx );
+ return -1;
+ }
+ return select_rfdidx[ridx];
+ }
+
+# endif /* HAVE_SELECT */
+
+# endif /* HAVE_POLL */
+
+# endif /* HAVE_DEVPOLL */
+
+#endif /* HAVE_KQUEUE */
--- /dev/null
+/* fdwatch.h - header file for fdwatch package
+**
+** This package abstracts the use of the select()/poll()/kqueue()
+** system calls. The basic function of these calls is to watch a set
+** of file descriptors for activity. select() originated in the BSD world,
+** while poll() came from SysV land, and their interfaces are somewhat
+** different. fdwatch lets you write your code to a single interface,
+** with the portability differences hidden inside the package.
+**
+** Usage is fairly simple. Call fdwatch_get_nfiles() to initialize
+** the package and find out how many fine descriptors are available.
+** Then each time through your main loop, call fdwatch_clear(), then
+** fdwatch_add_fd() for each of the descriptors you want to watch,
+** then call fdwatch() to actually perform the watch. After it returns
+** you can check which descriptors are ready via fdwatch_check_fd().
+**
+** If your descriptor set hasn't changed from the last time through
+** the loop, you can skip calling fdwatch_clear() and fdwatch_add_fd()
+** to save a little CPU time.
+**
+**
+** Copyright © 1999 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#ifndef _FDWATCH_H_
+#define _FDWATCH_H_
+
+#define FDW_READ 0
+#define FDW_WRITE 1
+
+#ifndef INFTIM
+#define INFTIM -1
+#endif /* INFTIM */
+
+/* Figure out how many file descriptors the system allows, and
+** initialize the fdwatch data structures. Returns -1 on failure.
+*/
+int fdwatch_get_nfiles( void );
+
+/* Add a descriptor to the watch list. rw is either FDW_READ or FDW_WRITE. */
+void fdwatch_add_fd( int fd, void* client_data, int rw );
+
+/* Delete a descriptor from the watch list. */
+void fdwatch_del_fd( int fd );
+
+/* Do the watch. Return value is the number of descriptors that are ready,
+** or 0 if the timeout expired, or -1 on errors. A timeout of INFTIM means
+** wait indefinitely.
+*/
+int fdwatch( long timeout_msecs );
+
+/* Check if a descriptor was ready. */
+int fdwatch_check_fd( int fd );
+
+/* Get the client data for the next returned event. Returns -1 when there
+** are no more events.
+*/
+void* fdwatch_get_next_client_data( void );
+
+/* Generate debugging statistics syslog message. */
+void fdwatch_logstats( long secs );
+
+#endif /* _FDWATCH_H_ */
--- /dev/null
+<HTML>
+<HEAD><TITLE>thttpd is running</TITLE></HEAD>
+<BODY BGCOLOR="#99cc99" TEXT="#000000" LINK="#2020ff" VLINK="#4040cc">
+
+<H3>thttpd is running</H3>
+
+<P>
+Looks like you got it working. Congrats.
+
+<P>
+Here's a link to the <A HREF="http://www.acme.com/software/thttpd/">thttpd web pages</A>.
+
+</BODY>
+</HTML>
--- /dev/null
+#! /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=:
+ 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
--- /dev/null
+/* libhttpd.c - HTTP protocol library
+**
+** Copyright © 1995,1998,1999,2000,2001,2015 by
+** Jef Poskanzer <jef@mail.acme.com>. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+
+#include "config.h"
+#include "version.h"
+
+#ifdef SHOW_SERVER_VERSION
+#define EXPOSED_SERVER_SOFTWARE SERVER_SOFTWARE
+#else /* SHOW_SERVER_VERSION */
+#define EXPOSED_SERVER_SOFTWARE "thttpd"
+#endif /* SHOW_SERVER_VERSION */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif /* HAVE_MEMORY_H */
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#ifdef HAVE_OSRELDATE_H
+#include <osreldate.h>
+#endif /* HAVE_OSRELDATE_H */
+
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#include "libhttpd.h"
+#include "mmc.h"
+#include "timers.h"
+#include "match.h"
+#include "tdate_parse.h"
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#ifndef SHUT_WR
+#define SHUT_WR 1
+#endif
+
+#ifndef HAVE_INT64T
+typedef long long int64_t;
+#endif
+
+#ifndef HAVE_SOCKLENT
+typedef int socklen_t;
+#endif
+
+#ifdef __CYGWIN__
+#define timezone _timezone
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+/* Forwards. */
+static void check_options( void );
+static void free_httpd_server( httpd_server* hs );
+static int initialize_listen_socket( httpd_sockaddr* saP );
+static void add_response( httpd_conn* hc, char* str );
+static void send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, off_t length, time_t mod );
+static void send_response( httpd_conn* hc, int status, char* title, char* extraheads, char* form, char* arg );
+static void send_response_tail( httpd_conn* hc );
+static void defang( char* str, char* dfstr, int dfsize );
+#ifdef ERR_DIR
+static int send_err_file( httpd_conn* hc, int status, char* title, char* extraheads, char* filename );
+#endif /* ERR_DIR */
+#ifdef AUTH_FILE
+static void send_authenticate( httpd_conn* hc, char* realm );
+static int b64_decode( const char* str, unsigned char* space, int size );
+static int auth_check( httpd_conn* hc, char* dirname );
+static int auth_check2( httpd_conn* hc, char* dirname );
+#endif /* AUTH_FILE */
+static void send_dirredirect( httpd_conn* hc );
+static int hexit( char c );
+static void strdecode( char* to, char* from );
+#ifdef GENERATE_INDEXES
+static void strencode( char* to, int tosize, char* from );
+#endif /* GENERATE_INDEXES */
+#ifdef TILDE_MAP_1
+static int tilde_map_1( httpd_conn* hc );
+#endif /* TILDE_MAP_1 */
+#ifdef TILDE_MAP_2
+static int tilde_map_2( httpd_conn* hc );
+#endif /* TILDE_MAP_2 */
+static int vhost_map( httpd_conn* hc );
+static char* expand_symlinks( char* path, char** restP, int no_symlink_check, int tildemapped );
+static char* bufgets( httpd_conn* hc );
+static void de_dotdot( char* file );
+static void init_mime( void );
+static void figure_mime( httpd_conn* hc );
+#ifdef CGI_TIMELIMIT
+static void cgi_kill2( ClientData client_data, struct timeval* nowP );
+static void cgi_kill( ClientData client_data, struct timeval* nowP );
+#endif /* CGI_TIMELIMIT */
+#ifdef GENERATE_INDEXES
+static int ls( httpd_conn* hc );
+#endif /* GENERATE_INDEXES */
+static char* build_env( char* fmt, char* arg );
+#ifdef SERVER_NAME_LIST
+static char* hostname_map( char* hostname );
+#endif /* SERVER_NAME_LIST */
+static char** make_envp( httpd_conn* hc );
+static char** make_argp( httpd_conn* hc );
+static void cgi_interpose_input( httpd_conn* hc, int wfd );
+static void post_post_garbage_hack( httpd_conn* hc );
+static void cgi_interpose_output( httpd_conn* hc, int rfd );
+static void cgi_child( httpd_conn* hc );
+static int cgi( httpd_conn* hc );
+static int really_start_request( httpd_conn* hc, struct timeval* nowP );
+static void make_log_entry( httpd_conn* hc, struct timeval* nowP );
+static int check_referrer( httpd_conn* hc );
+static int really_check_referrer( httpd_conn* hc );
+static int sockaddr_check( httpd_sockaddr* saP );
+static size_t sockaddr_len( httpd_sockaddr* saP );
+static int my_snprintf( char* str, size_t size, const char* format, ... );
+#ifndef HAVE_ATOLL
+static long long atoll( const char* str );
+#endif /* HAVE_ATOLL */
+
+
+/* This global keeps track of whether we are in the main process or a
+** sub-process. The reason is that httpd_write_response() can get called
+** in either context; when it is called from the main process it must use
+** non-blocking I/O to avoid stalling the server, but when it is called
+** from a sub-process it wants to use blocking I/O so that the whole
+** response definitely gets written. So, it checks this variable. A bit
+** of a hack but it seems to do the right thing.
+*/
+static int sub_process = 0;
+
+
+static void
+check_options( void )
+ {
+#if defined(TILDE_MAP_1) && defined(TILDE_MAP_2)
+ syslog( LOG_CRIT, "both TILDE_MAP_1 and TILDE_MAP_2 are defined" );
+ exit( 1 );
+#endif /* both */
+ }
+
+
+static void
+free_httpd_server( httpd_server* hs )
+ {
+ if ( hs->binding_hostname != (char*) 0 )
+ free( (void*) hs->binding_hostname );
+ if ( hs->cwd != (char*) 0 )
+ free( (void*) hs->cwd );
+ if ( hs->cgi_pattern != (char*) 0 )
+ free( (void*) hs->cgi_pattern );
+ if ( hs->charset != (char*) 0 )
+ free( (void*) hs->charset );
+ if ( hs->p3p != (char*) 0 )
+ free( (void*) hs->p3p );
+ if ( hs->url_pattern != (char*) 0 )
+ free( (void*) hs->url_pattern );
+ if ( hs->local_pattern != (char*) 0 )
+ free( (void*) hs->local_pattern );
+ free( (void*) hs );
+ }
+
+
+httpd_server*
+httpd_initialize(
+ char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P,
+ unsigned short port, char* cgi_pattern, int cgi_limit, char* charset,
+ char* p3p, int max_age, char* cwd, int no_log, FILE* logfp,
+ int no_symlink_check, int vhost, int global_passwd, char* url_pattern,
+ char* local_pattern, int no_empty_referrers )
+ {
+ httpd_server* hs;
+ static char ghnbuf[256];
+ char* cp;
+
+ check_options();
+
+ hs = NEW( httpd_server, 1 );
+ if ( hs == (httpd_server*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory allocating an httpd_server" );
+ return (httpd_server*) 0;
+ }
+
+ if ( hostname != (char*) 0 )
+ {
+ hs->binding_hostname = strdup( hostname );
+ if ( hs->binding_hostname == (char*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory copying hostname" );
+ return (httpd_server*) 0;
+ }
+ hs->server_hostname = hs->binding_hostname;
+ }
+ else
+ {
+ hs->binding_hostname = (char*) 0;
+ hs->server_hostname = (char*) 0;
+ if ( gethostname( ghnbuf, sizeof(ghnbuf) ) < 0 )
+ ghnbuf[0] = '\0';
+#ifdef SERVER_NAME_LIST
+ if ( ghnbuf[0] != '\0' )
+ hs->server_hostname = hostname_map( ghnbuf );
+#endif /* SERVER_NAME_LIST */
+ if ( hs->server_hostname == (char*) 0 )
+ {
+#ifdef SERVER_NAME
+ hs->server_hostname = SERVER_NAME;
+#else /* SERVER_NAME */
+ if ( ghnbuf[0] != '\0' )
+ hs->server_hostname = ghnbuf;
+#endif /* SERVER_NAME */
+ }
+ }
+
+ hs->port = port;
+ if ( cgi_pattern == (char*) 0 )
+ hs->cgi_pattern = (char*) 0;
+ else
+ {
+ /* Nuke any leading slashes. */
+ if ( cgi_pattern[0] == '/' )
+ ++cgi_pattern;
+ hs->cgi_pattern = strdup( cgi_pattern );
+ if ( hs->cgi_pattern == (char*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory copying cgi_pattern" );
+ return (httpd_server*) 0;
+ }
+ /* Nuke any leading slashes in the cgi pattern. */
+ while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 )
+ (void) ol_strcpy( cp + 1, cp + 2 );
+ }
+ hs->cgi_limit = cgi_limit;
+ hs->cgi_count = 0;
+ hs->charset = strdup( charset );
+ hs->p3p = strdup( p3p );
+ hs->max_age = max_age;
+ hs->cwd = strdup( cwd );
+ if ( hs->cwd == (char*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory copying cwd" );
+ return (httpd_server*) 0;
+ }
+ if ( url_pattern == (char*) 0 )
+ hs->url_pattern = (char*) 0;
+ else
+ {
+ hs->url_pattern = strdup( url_pattern );
+ if ( hs->url_pattern == (char*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory copying url_pattern" );
+ return (httpd_server*) 0;
+ }
+ }
+ if ( local_pattern == (char*) 0 )
+ hs->local_pattern = (char*) 0;
+ else
+ {
+ hs->local_pattern = strdup( local_pattern );
+ if ( hs->local_pattern == (char*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory copying local_pattern" );
+ return (httpd_server*) 0;
+ }
+ }
+ hs->no_log = no_log;
+ hs->logfp = (FILE*) 0;
+ httpd_set_logfp( hs, logfp );
+ hs->no_symlink_check = no_symlink_check;
+ hs->vhost = vhost;
+ hs->global_passwd = global_passwd;
+ hs->no_empty_referrers = no_empty_referrers;
+
+ /* Initialize listen sockets. Try v6 first because of a Linux peculiarity;
+ ** like some other systems, it has magical v6 sockets that also listen for
+ ** v4, but in Linux if you bind a v4 socket first then the v6 bind fails.
+ */
+ if ( sa6P == (httpd_sockaddr*) 0 )
+ hs->listen6_fd = -1;
+ else
+ hs->listen6_fd = initialize_listen_socket( sa6P );
+ if ( sa4P == (httpd_sockaddr*) 0 )
+ hs->listen4_fd = -1;
+ else
+ hs->listen4_fd = initialize_listen_socket( sa4P );
+ /* If we didn't get any valid sockets, fail. */
+ if ( hs->listen4_fd == -1 && hs->listen6_fd == -1 )
+ {
+ free_httpd_server( hs );
+ return (httpd_server*) 0;
+ }
+
+ init_mime();
+
+ /* Done initializing. */
+ if ( hs->binding_hostname == (char*) 0 )
+ syslog(
+ LOG_NOTICE, "%.80s starting on port %d", SERVER_SOFTWARE,
+ (int) hs->port );
+ else
+ syslog(
+ LOG_NOTICE, "%.80s starting on %.80s, port %d", SERVER_SOFTWARE,
+ httpd_ntoa( hs->listen4_fd != -1 ? sa4P : sa6P ),
+ (int) hs->port );
+ return hs;
+ }
+
+
+static int
+initialize_listen_socket( httpd_sockaddr* saP )
+ {
+ int listen_fd;
+ int on, flags;
+
+ /* Check sockaddr. */
+ if ( ! sockaddr_check( saP ) )
+ {
+ syslog( LOG_CRIT, "unknown sockaddr family on listen socket" );
+ return -1;
+ }
+
+ /* Create socket. */
+ listen_fd = socket( saP->sa.sa_family, SOCK_STREAM, 0 );
+ if ( listen_fd < 0 )
+ {
+ syslog( LOG_CRIT, "socket %.80s - %m", httpd_ntoa( saP ) );
+ return -1;
+ }
+ (void) fcntl( listen_fd, F_SETFD, 1 );
+
+ /* Allow reuse of local addresses. */
+ on = 1;
+ if ( setsockopt(
+ listen_fd, SOL_SOCKET, SO_REUSEADDR, (char*) &on,
+ sizeof(on) ) < 0 )
+ syslog( LOG_CRIT, "setsockopt SO_REUSEADDR - %m" );
+
+ /* Bind to it. */
+ if ( bind( listen_fd, &saP->sa, sockaddr_len( saP ) ) < 0 )
+ {
+ syslog(
+ LOG_CRIT, "bind %.80s - %m", httpd_ntoa( saP ) );
+ (void) close( listen_fd );
+ return -1;
+ }
+
+ /* Set the listen file descriptor to no-delay / non-blocking mode. */
+ flags = fcntl( listen_fd, F_GETFL, 0 );
+ if ( flags == -1 )
+ {
+ syslog( LOG_CRIT, "fcntl F_GETFL - %m" );
+ (void) close( listen_fd );
+ return -1;
+ }
+ if ( fcntl( listen_fd, F_SETFL, flags | O_NDELAY ) < 0 )
+ {
+ syslog( LOG_CRIT, "fcntl O_NDELAY - %m" );
+ (void) close( listen_fd );
+ return -1;
+ }
+
+ /* Start a listen going. */
+ if ( listen( listen_fd, LISTEN_BACKLOG ) < 0 )
+ {
+ syslog( LOG_CRIT, "listen - %m" );
+ (void) close( listen_fd );
+ return -1;
+ }
+
+ /* Use accept filtering, if available. */
+#ifdef SO_ACCEPTFILTER
+ {
+#if ( __FreeBSD_version >= 411000 )
+#define ACCEPT_FILTER_NAME "httpready"
+#else
+#define ACCEPT_FILTER_NAME "dataready"
+#endif
+ struct accept_filter_arg af;
+ (void) bzero( &af, sizeof(af) );
+ (void) strcpy( af.af_name, ACCEPT_FILTER_NAME );
+ (void) setsockopt(
+ listen_fd, SOL_SOCKET, SO_ACCEPTFILTER, (char*) &af, sizeof(af) );
+ }
+#endif /* SO_ACCEPTFILTER */
+
+ return listen_fd;
+ }
+
+
+void
+httpd_set_logfp( httpd_server* hs, FILE* logfp )
+ {
+ if ( hs->logfp != (FILE*) 0 )
+ (void) fclose( hs->logfp );
+ hs->logfp = logfp;
+ }
+
+
+void
+httpd_terminate( httpd_server* hs )
+ {
+ httpd_unlisten( hs );
+ if ( hs->logfp != (FILE*) 0 )
+ (void) fclose( hs->logfp );
+ free_httpd_server( hs );
+ }
+
+
+void
+httpd_unlisten( httpd_server* hs )
+ {
+ if ( hs->listen4_fd != -1 )
+ {
+ (void) close( hs->listen4_fd );
+ hs->listen4_fd = -1;
+ }
+ if ( hs->listen6_fd != -1 )
+ {
+ (void) close( hs->listen6_fd );
+ hs->listen6_fd = -1;
+ }
+ }
+
+
+/* Conditional macro to allow two alternate forms for use in the built-in
+** error pages. If EXPLICIT_ERROR_PAGES is defined, the second and more
+** explicit error form is used; otherwise, the first and more generic
+** form is used.
+*/
+#ifdef EXPLICIT_ERROR_PAGES
+#define ERROR_FORM(a,b) b
+#else /* EXPLICIT_ERROR_PAGES */
+#define ERROR_FORM(a,b) a
+#endif /* EXPLICIT_ERROR_PAGES */
+
+
+static char* ok200title = "OK";
+static char* ok206title = "Partial Content";
+
+static char* err302title = "Found";
+static char* err302form = "The actual URL is '%.80s'.\n";
+
+static char* err304title = "Not Modified";
+
+char* httpd_err400title = "Bad Request";
+char* httpd_err400form =
+ "Your request has bad syntax or is inherently impossible to satisfy.\n";
+
+#ifdef AUTH_FILE
+static char* err401title = "Unauthorized";
+static char* err401form =
+ "Authorization required for the URL '%.80s'.\n";
+#endif /* AUTH_FILE */
+
+static char* err403title = "Forbidden";
+#ifndef EXPLICIT_ERROR_PAGES
+static char* err403form =
+ "You do not have permission to get URL '%.80s' from this server.\n";
+#endif /* !EXPLICIT_ERROR_PAGES */
+
+static char* err404title = "Not Found";
+static char* err404form =
+ "The requested URL '%.80s' was not found on this server.\n";
+
+char* httpd_err408title = "Request Timeout";
+char* httpd_err408form =
+ "No request appeared within a reasonable time period.\n";
+
+static char* err451title = "Unavailable For Legal Reasons";
+static char* err451form =
+ "You do not have legal permission to get URL '%.80s' from this server.\n";
+
+static char* err500title = "Internal Error";
+static char* err500form =
+ "There was an unusual problem serving the requested URL '%.80s'.\n";
+
+static char* err501title = "Not Implemented";
+static char* err501form =
+ "The requested method '%.80s' is not implemented by this server.\n";
+
+char* httpd_err503title = "Service Temporarily Overloaded";
+char* httpd_err503form =
+ "The requested URL '%.80s' is temporarily overloaded. Please try again later.\n";
+
+
+/* Append a string to the buffer waiting to be sent as response. */
+static void
+add_response( httpd_conn* hc, char* str )
+ {
+ size_t len;
+
+ len = strlen( str );
+ httpd_realloc_str( &hc->response, &hc->maxresponse, hc->responselen + len );
+ (void) memmove( &(hc->response[hc->responselen]), str, len );
+ hc->responselen += len;
+ }
+
+/* Send the buffered response. */
+void
+httpd_write_response( httpd_conn* hc )
+ {
+ /* If we are in a sub-process, turn off no-delay mode. */
+ if ( sub_process )
+ httpd_clear_ndelay( hc->conn_fd );
+ /* Send the response, if necessary. */
+ if ( hc->responselen > 0 )
+ {
+ (void) httpd_write_fully( hc->conn_fd, hc->response, hc->responselen );
+ hc->responselen = 0;
+ }
+ }
+
+
+/* Set no-delay / non-blocking mode on a socket. */
+void
+httpd_set_ndelay( int fd )
+ {
+ int flags, newflags;
+
+ flags = fcntl( fd, F_GETFL, 0 );
+ if ( flags != -1 )
+ {
+ newflags = flags | (int) O_NDELAY;
+ if ( newflags != flags )
+ (void) fcntl( fd, F_SETFL, newflags );
+ }
+ }
+
+
+/* Clear no-delay / non-blocking mode on a socket. */
+void
+httpd_clear_ndelay( int fd )
+ {
+ int flags, newflags;
+
+ flags = fcntl( fd, F_GETFL, 0 );
+ if ( flags != -1 )
+ {
+ newflags = flags & ~ (int) O_NDELAY;
+ if ( newflags != flags )
+ (void) fcntl( fd, F_SETFL, newflags );
+ }
+ }
+
+
+static void
+send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, off_t length, time_t mod )
+ {
+ time_t now, expires;
+ const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT";
+ char nowbuf[100];
+ char modbuf[100];
+ char expbuf[100];
+ char fixed_type[500];
+ char buf[1000];
+ int partial_content;
+ int s100;
+
+ hc->status = status;
+ hc->bytes_to_send = length;
+ if ( hc->mime_flag )
+ {
+ if ( status == 200 && hc->got_range &&
+ ( hc->last_byte_index >= hc->first_byte_index ) &&
+ ( ( hc->last_byte_index != length - 1 ) ||
+ ( hc->first_byte_index != 0 ) ) &&
+ ( hc->range_if == (time_t) -1 ||
+ hc->range_if == hc->sb.st_mtime ) )
+ {
+ partial_content = 1;
+ hc->status = status = 206;
+ title = ok206title;
+ }
+ else
+ {
+ partial_content = 0;
+ hc->got_range = 0;
+ }
+
+ now = time( (time_t*) 0 );
+ if ( mod == (time_t) 0 )
+ mod = now;
+ (void) strftime( nowbuf, sizeof(nowbuf), rfc1123fmt, gmtime( &now ) );
+ (void) strftime( modbuf, sizeof(modbuf), rfc1123fmt, gmtime( &mod ) );
+ (void) my_snprintf(
+ fixed_type, sizeof(fixed_type), type, hc->hs->charset );
+ (void) my_snprintf( buf, sizeof(buf),
+ "%.20s %d %s\015\012Server: %s\015\012Content-Type: %s\015\012Date: %s\015\012Last-Modified: %s\015\012Accept-Ranges: bytes\015\012Connection: close\015\012",
+ hc->protocol, status, title, EXPOSED_SERVER_SOFTWARE, fixed_type,
+ nowbuf, modbuf );
+ add_response( hc, buf );
+ s100 = status / 100;
+ if ( s100 != 2 && s100 != 3 )
+ {
+ (void) my_snprintf( buf, sizeof(buf),
+ "Cache-Control: no-cache,no-store\015\012" );
+ add_response( hc, buf );
+ }
+ if ( encodings[0] != '\0' )
+ {
+ (void) my_snprintf( buf, sizeof(buf),
+ "Content-Encoding: %s\015\012", encodings );
+ add_response( hc, buf );
+ }
+ if ( partial_content )
+ {
+ (void) my_snprintf( buf, sizeof(buf),
+ "Content-Range: bytes %lld-%lld/%lld\015\012Content-Length: %lld\015\012",
+ (long long) hc->first_byte_index,
+ (long long) hc->last_byte_index,
+ (long long) length,
+ (long long) ( hc->last_byte_index - hc->first_byte_index + 1 ) );
+ add_response( hc, buf );
+ }
+ else if ( length >= 0 )
+ {
+ (void) my_snprintf( buf, sizeof(buf),
+ "Content-Length: %lld\015\012", (long long) length );
+ add_response( hc, buf );
+ }
+ if ( hc->hs->p3p[0] != '\0' )
+ {
+ (void) my_snprintf( buf, sizeof(buf), "P3P: %s\015\012", hc->hs->p3p );
+ add_response( hc, buf );
+ }
+ if ( hc->hs->max_age >= 0 )
+ {
+ expires = now + hc->hs->max_age;
+ (void) strftime(
+ expbuf, sizeof(expbuf), rfc1123fmt, gmtime( &expires ) );
+ (void) my_snprintf( buf, sizeof(buf),
+ "Cache-Control: max-age=%d\015\012Expires: %s\015\012",
+ hc->hs->max_age, expbuf );
+ add_response( hc, buf );
+ }
+ if ( extraheads[0] != '\0' )
+ add_response( hc, extraheads );
+ add_response( hc, "\015\012" );
+ }
+ }
+
+
+static int str_alloc_count = 0;
+static size_t str_alloc_size = 0;
+
+void
+httpd_realloc_str( char** strP, size_t* maxsizeP, size_t size )
+ {
+ if ( *maxsizeP == 0 )
+ {
+ *maxsizeP = MAX( 200, size + 100 );
+ *strP = NEW( char, *maxsizeP + 1 );
+ ++str_alloc_count;
+ str_alloc_size += *maxsizeP;
+ }
+ else if ( size > *maxsizeP )
+ {
+ str_alloc_size -= *maxsizeP;
+ *maxsizeP = MAX( *maxsizeP * 2, size * 5 / 4 );
+ *strP = RENEW( *strP, char, *maxsizeP + 1 );
+ str_alloc_size += *maxsizeP;
+ }
+ else
+ return;
+ if ( *strP == (char*) 0 )
+ {
+ syslog(
+ LOG_ERR, "out of memory reallocating a string to %ld bytes",
+ (long) *maxsizeP );
+ exit( 1 );
+ }
+ }
+
+
+static void
+send_response( httpd_conn* hc, int status, char* title, char* extraheads, char* form, char* arg )
+ {
+ char defanged_arg[1000], buf[2000];
+
+ send_mime(
+ hc, status, title, "", extraheads, "text/html; charset=%s", (off_t) -1,
+ (time_t) 0 );
+ (void) my_snprintf( buf, sizeof(buf), "\
+<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n\
+\n\
+<html>\n\
+\n\
+ <head>\n\
+ <meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\">\n\
+ <title>%d %s</title>\n\
+ </head>\n\
+\n\
+ <body bgcolor=\"#cc9999\" text=\"#000000\" link=\"#2020ff\" vlink=\"#4040cc\">\n\
+\n\
+ <h2>%d %s</h2>\n",
+ status, title, status, title );
+ add_response( hc, buf );
+ defang( arg, defanged_arg, sizeof(defanged_arg) );
+ (void) my_snprintf( buf, sizeof(buf), form, defanged_arg );
+ add_response( hc, buf );
+ if ( match( "**MSIE**", hc->useragent ) )
+ {
+ int n;
+ add_response( hc, "<!--\n" );
+ for ( n = 0; n < 6; ++n )
+ add_response( hc, "Padding so that MSIE deigns to show this error instead of its own canned one.\n");
+ add_response( hc, "-->\n" );
+ }
+ send_response_tail( hc );
+ }
+
+
+static void
+send_response_tail( httpd_conn* hc )
+ {
+ char buf[1000];
+
+ (void) my_snprintf( buf, sizeof(buf), "\
+ <hr>\n\
+\n\
+ <address><a href=\"%s\">%s</a></address>\n\
+\n\
+ </body>\n\
+\n\
+</html>\n",
+ SERVER_ADDRESS, EXPOSED_SERVER_SOFTWARE );
+ add_response( hc, buf );
+ }
+
+
+static void
+defang( char* str, char* dfstr, int dfsize )
+ {
+ char* cp1;
+ char* cp2;
+
+ for ( cp1 = str, cp2 = dfstr;
+ *cp1 != '\0' && cp2 - dfstr < dfsize - 5;
+ ++cp1, ++cp2 )
+ {
+ switch ( *cp1 )
+ {
+ case '<':
+ *cp2++ = '&';
+ *cp2++ = 'l';
+ *cp2++ = 't';
+ *cp2 = ';';
+ break;
+ case '>':
+ *cp2++ = '&';
+ *cp2++ = 'g';
+ *cp2++ = 't';
+ *cp2 = ';';
+ break;
+ default:
+ *cp2 = *cp1;
+ break;
+ }
+ }
+ *cp2 = '\0';
+ }
+
+
+void
+httpd_send_err( httpd_conn* hc, int status, char* title, char* extraheads, char* form, char* arg )
+ {
+#ifdef ERR_DIR
+
+ char filename[1000];
+
+ /* Try virtual host error page. */
+ if ( hc->hs->vhost && hc->hostdir[0] != '\0' )
+ {
+ (void) my_snprintf( filename, sizeof(filename),
+ "%s/%s/err%d.html", hc->hostdir, ERR_DIR, status );
+ if ( send_err_file( hc, status, title, extraheads, filename ) )
+ return;
+ }
+
+ /* Try server-wide error page. */
+ (void) my_snprintf( filename, sizeof(filename),
+ "%s/err%d.html", ERR_DIR, status );
+ if ( send_err_file( hc, status, title, extraheads, filename ) )
+ return;
+
+ /* Fall back on built-in error page. */
+ send_response( hc, status, title, extraheads, form, arg );
+
+#else /* ERR_DIR */
+
+ send_response( hc, status, title, extraheads, form, arg );
+
+#endif /* ERR_DIR */
+ }
+
+
+#ifdef ERR_DIR
+static int
+send_err_file( httpd_conn* hc, int status, char* title, char* extraheads, char* filename )
+ {
+ FILE* fp;
+ char buf[1000];
+ size_t r;
+
+ fp = fopen( filename, "r" );
+ if ( fp == (FILE*) 0 )
+ return 0;
+ send_mime(
+ hc, status, title, "", extraheads, "text/html; charset=%s", (off_t) -1,
+ (time_t) 0 );
+ for (;;)
+ {
+ r = fread( buf, 1, sizeof(buf) - 1, fp );
+ if ( r == 0 )
+ break;
+ buf[r] = '\0';
+ add_response( hc, buf );
+ }
+ (void) fclose( fp );
+
+#ifdef ERR_APPEND_SERVER_INFO
+ send_response_tail( hc );
+#endif /* ERR_APPEND_SERVER_INFO */
+
+ return 1;
+ }
+#endif /* ERR_DIR */
+
+
+#ifdef AUTH_FILE
+
+static void
+send_authenticate( httpd_conn* hc, char* realm )
+ {
+ static char* header;
+ static size_t maxheader = 0;
+ static char headstr[] = "WWW-Authenticate: Basic realm=\"";
+
+ httpd_realloc_str(
+ &header, &maxheader, sizeof(headstr) + strlen( realm ) + 3 );
+ (void) my_snprintf( header, maxheader, "%s%s\"\015\012", headstr, realm );
+ httpd_send_err( hc, 401, err401title, header, err401form, hc->encodedurl );
+ /* If the request was a POST then there might still be data to be read,
+ ** so we need to do a lingering close.
+ */
+ if ( hc->method == METHOD_POST )
+ hc->should_linger = 1;
+ }
+
+
+/* Base-64 decoding. This represents binary data as printable ASCII
+** characters. Three 8-bit binary bytes are turned into four 6-bit
+** values, like so:
+**
+** [11111111] [22222222] [33333333]
+**
+** [111111] [112222] [222233] [333333]
+**
+** Then the 6-bit values are represented using the characters "A-Za-z0-9+/".
+*/
+
+static int b64_decode_table[256] = {
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */
+ 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */
+ 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */
+ -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */
+ 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */
+ };
+
+/* Do base-64 decoding on a string. Ignore any non-base64 bytes.
+** Return the actual number of bytes generated. The decoded size will
+** be at most 3/4 the size of the encoded, and may be smaller if there
+** are padding characters (blanks, newlines).
+*/
+static int
+b64_decode( const char* str, unsigned char* space, int size )
+ {
+ const char* cp;
+ int space_idx, phase;
+ int d, prev_d = 0;
+ unsigned char c;
+
+ space_idx = 0;
+ phase = 0;
+ for ( cp = str; *cp != '\0'; ++cp )
+ {
+ d = b64_decode_table[(int) ((unsigned char) *cp)];
+ if ( d != -1 )
+ {
+ switch ( phase )
+ {
+ case 0:
+ ++phase;
+ break;
+ case 1:
+ c = ( ( prev_d << 2 ) | ( ( d & 0x30 ) >> 4 ) );
+ if ( space_idx < size )
+ space[space_idx++] = c;
+ ++phase;
+ break;
+ case 2:
+ c = ( ( ( prev_d & 0xf ) << 4 ) | ( ( d & 0x3c ) >> 2 ) );
+ if ( space_idx < size )
+ space[space_idx++] = c;
+ ++phase;
+ break;
+ case 3:
+ c = ( ( ( prev_d & 0x03 ) << 6 ) | d );
+ if ( space_idx < size )
+ space[space_idx++] = c;
+ phase = 0;
+ break;
+ }
+ prev_d = d;
+ }
+ }
+ return space_idx;
+ }
+
+
+/* Returns -1 == unauthorized, 0 == no auth file, 1 = authorized. */
+static int
+auth_check( httpd_conn* hc, char* dirname )
+ {
+ if ( hc->hs->global_passwd )
+ {
+ char* topdir;
+ if ( hc->hs->vhost && hc->hostdir[0] != '\0' )
+ topdir = hc->hostdir;
+ else
+ topdir = ".";
+ switch ( auth_check2( hc, topdir ) )
+ {
+ case -1:
+ return -1;
+ case 1:
+ return 1;
+ }
+ }
+ return auth_check2( hc, dirname );
+ }
+
+
+/* Returns -1 == unauthorized, 0 == no auth file, 1 = authorized. */
+static int
+auth_check2( httpd_conn* hc, char* dirname )
+ {
+ static char* authpath;
+ static size_t maxauthpath = 0;
+ struct stat sb;
+ char authinfo[500];
+ char* authpass;
+ char* colon;
+ int l;
+ FILE* fp;
+ char line[500];
+ char* cryp;
+ static char* prevauthpath;
+ static size_t maxprevauthpath = 0;
+ static time_t prevmtime;
+ static char* prevuser;
+ static size_t maxprevuser = 0;
+ static char* prevcryp;
+ static size_t maxprevcryp = 0;
+
+ /* Construct auth filename. */
+ httpd_realloc_str(
+ &authpath, &maxauthpath, strlen( dirname ) + 1 + sizeof(AUTH_FILE) );
+ (void) my_snprintf( authpath, maxauthpath, "%s/%s", dirname, AUTH_FILE );
+
+ /* Does this directory have an auth file? */
+ if ( stat( authpath, &sb ) < 0 )
+ /* Nope, let the request go through. */
+ return 0;
+
+ /* Does this request contain basic authorization info? */
+ if ( hc->authorization[0] == '\0' ||
+ strncmp( hc->authorization, "Basic ", 6 ) != 0 )
+ {
+ /* Nope, return a 401 Unauthorized. */
+ send_authenticate( hc, dirname );
+ return -1;
+ }
+
+ /* Decode it. */
+ l = b64_decode(
+ &(hc->authorization[6]), (unsigned char*) authinfo,
+ sizeof(authinfo) - 1 );
+ authinfo[l] = '\0';
+ /* Split into user and password. */
+ authpass = strchr( authinfo, ':' );
+ if ( authpass == (char*) 0 )
+ {
+ /* No colon? Bogus auth info. */
+ send_authenticate( hc, dirname );
+ return -1;
+ }
+ *authpass++ = '\0';
+ /* If there are more fields, cut them off. */
+ colon = strchr( authpass, ':' );
+ if ( colon != (char*) 0 )
+ *colon = '\0';
+
+ /* See if we have a cached entry and can use it. */
+ if ( maxprevauthpath != 0 &&
+ strcmp( authpath, prevauthpath ) == 0 &&
+ sb.st_mtime == prevmtime &&
+ strcmp( authinfo, prevuser ) == 0 )
+ {
+ /* Yes. Check against the cached encrypted password. */
+ if ( strcmp( crypt( authpass, prevcryp ), prevcryp ) == 0 )
+ {
+ /* Ok! */
+ httpd_realloc_str(
+ &hc->remoteuser, &hc->maxremoteuser, strlen( authinfo ) );
+ (void) strcpy( hc->remoteuser, authinfo );
+ return 1;
+ }
+ else
+ {
+ /* No. */
+ send_authenticate( hc, dirname );
+ return -1;
+ }
+ }
+
+ /* Open the password file. */
+ fp = fopen( authpath, "r" );
+ if ( fp == (FILE*) 0 )
+ {
+ /* The file exists but we can't open it? Disallow access. */
+ syslog(
+ LOG_ERR, "%.80s auth file %.80s could not be opened - %m",
+ httpd_ntoa( &hc->client_addr ), authpath );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' is protected by an authentication file, but the authentication file cannot be opened.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+
+ /* Read it. */
+ while ( fgets( line, sizeof(line), fp ) != (char*) 0 )
+ {
+ /* Nuke newline. */
+ l = strlen( line );
+ if ( line[l - 1] == '\n' )
+ line[l - 1] = '\0';
+ /* Split into user and encrypted password. */
+ cryp = strchr( line, ':' );
+ if ( cryp == (char*) 0 )
+ continue;
+ *cryp++ = '\0';
+ /* Is this the right user? */
+ if ( strcmp( line, authinfo ) == 0 )
+ {
+ /* Yes. */
+ (void) fclose( fp );
+ /* So is the password right? */
+ if ( strcmp( crypt( authpass, cryp ), cryp ) == 0 )
+ {
+ /* Ok! */
+ httpd_realloc_str(
+ &hc->remoteuser, &hc->maxremoteuser, strlen( line ) );
+ (void) strcpy( hc->remoteuser, line );
+ /* And cache this user's info for next time. */
+ httpd_realloc_str(
+ &prevauthpath, &maxprevauthpath, strlen( authpath ) );
+ (void) strcpy( prevauthpath, authpath );
+ prevmtime = sb.st_mtime;
+ httpd_realloc_str(
+ &prevuser, &maxprevuser, strlen( authinfo ) );
+ (void) strcpy( prevuser, authinfo );
+ httpd_realloc_str( &prevcryp, &maxprevcryp, strlen( cryp ) );
+ (void) strcpy( prevcryp, cryp );
+ return 1;
+ }
+ else
+ {
+ /* No. */
+ send_authenticate( hc, dirname );
+ return -1;
+ }
+ }
+ }
+
+ /* Didn't find that user. Access denied. */
+ (void) fclose( fp );
+ send_authenticate( hc, dirname );
+ return -1;
+ }
+
+#endif /* AUTH_FILE */
+
+
+static void
+send_dirredirect( httpd_conn* hc )
+ {
+ static char* location;
+ static char* header;
+ static size_t maxlocation = 0, maxheader = 0;
+ static char headstr[] = "Location: ";
+
+ if ( hc->query[0] != '\0')
+ {
+ char* cp = strchr( hc->encodedurl, '?' );
+ if ( cp != (char*) 0 ) /* should always find it */
+ *cp = '\0';
+ httpd_realloc_str(
+ &location, &maxlocation,
+ strlen( hc->encodedurl ) + 2 + strlen( hc->query ) );
+ (void) my_snprintf( location, maxlocation,
+ "%s/?%s", hc->encodedurl, hc->query );
+ }
+ else
+ {
+ httpd_realloc_str(
+ &location, &maxlocation, strlen( hc->encodedurl ) + 1 );
+ (void) my_snprintf( location, maxlocation,
+ "%s/", hc->encodedurl );
+ }
+ httpd_realloc_str(
+ &header, &maxheader, sizeof(headstr) + strlen( location ) );
+ (void) my_snprintf( header, maxheader,
+ "%s%s\015\012", headstr, location );
+ send_response( hc, 302, err302title, header, err302form, location );
+ }
+
+
+char*
+httpd_method_str( int method )
+ {
+ switch ( method )
+ {
+ case METHOD_GET: return "GET";
+ case METHOD_HEAD: return "HEAD";
+ case METHOD_POST: return "POST";
+ case METHOD_PUT: return "PUT";
+ case METHOD_DELETE: return "DELETE";
+ case METHOD_TRACE: return "TRACE";
+ default: return "UNKNOWN";
+ }
+ }
+
+
+static int
+hexit( char c )
+ {
+ if ( c >= '0' && c <= '9' )
+ return c - '0';
+ if ( c >= 'a' && c <= 'f' )
+ return c - 'a' + 10;
+ if ( c >= 'A' && c <= 'F' )
+ return c - 'A' + 10;
+ return 0; /* shouldn't happen, we're guarded by isxdigit() */
+ }
+
+
+/* Copies and decodes a string. It's ok for from and to to be the
+** same string.
+*/
+static void
+strdecode( char* to, char* from )
+ {
+ for ( ; *from != '\0'; ++to, ++from )
+ {
+ if ( from[0] == '%' && isxdigit( from[1] ) && isxdigit( from[2] ) )
+ {
+ *to = hexit( from[1] ) * 16 + hexit( from[2] );
+ from += 2;
+ }
+ else
+ *to = *from;
+ }
+ *to = '\0';
+ }
+
+
+#ifdef GENERATE_INDEXES
+/* Copies and encodes a string. */
+static void
+strencode( char* to, int tosize, char* from )
+ {
+ int tolen;
+
+ for ( tolen = 0; *from != '\0' && tolen + 4 < tosize; ++from )
+ {
+ if ( isalnum(*from) || strchr( "/_.-~", *from ) != (char*) 0 )
+ {
+ *to = *from;
+ ++to;
+ ++tolen;
+ }
+ else
+ {
+ (void) sprintf( to, "%%%02x", (int) *from & 0xff );
+ to += 3;
+ tolen += 3;
+ }
+ }
+ *to = '\0';
+ }
+#endif /* GENERATE_INDEXES */
+
+
+#ifdef TILDE_MAP_1
+/* Map a ~username/whatever URL into <prefix>/username. */
+static int
+tilde_map_1( httpd_conn* hc )
+ {
+ static char* temp;
+ static size_t maxtemp = 0;
+ int len;
+ static char* prefix = TILDE_MAP_1;
+
+ len = strlen( hc->expnfilename ) - 1;
+ httpd_realloc_str( &temp, &maxtemp, len );
+ (void) strcpy( temp, &hc->expnfilename[1] );
+ httpd_realloc_str(
+ &hc->expnfilename, &hc->maxexpnfilename, strlen( prefix ) + 1 + len );
+ (void) strcpy( hc->expnfilename, prefix );
+ if ( prefix[0] != '\0' )
+ (void) strcat( hc->expnfilename, "/" );
+ (void) strcat( hc->expnfilename, temp );
+ return 1;
+ }
+#endif /* TILDE_MAP_1 */
+
+#ifdef TILDE_MAP_2
+/* Map a ~username/whatever URL into <user's homedir>/<postfix>. */
+static int
+tilde_map_2( httpd_conn* hc )
+ {
+ static char* temp;
+ static size_t maxtemp = 0;
+ static char* postfix = TILDE_MAP_2;
+ char* cp;
+ struct passwd* pw;
+ char* alt;
+ char* rest;
+
+ /* Get the username. */
+ httpd_realloc_str( &temp, &maxtemp, strlen( hc->expnfilename ) - 1 );
+ (void) strcpy( temp, &hc->expnfilename[1] );
+ cp = strchr( temp, '/' );
+ if ( cp != (char*) 0 )
+ *cp++ = '\0';
+ else
+ cp = "";
+
+ /* Get the passwd entry. */
+ pw = getpwnam( temp );
+ if ( pw == (struct passwd*) 0 )
+ return 0;
+
+ /* Set up altdir. */
+ httpd_realloc_str(
+ &hc->altdir, &hc->maxaltdir,
+ strlen( pw->pw_dir ) + 1 + strlen( postfix ) );
+ (void) strcpy( hc->altdir, pw->pw_dir );
+ if ( postfix[0] != '\0' )
+ {
+ (void) strcat( hc->altdir, "/" );
+ (void) strcat( hc->altdir, postfix );
+ }
+ alt = expand_symlinks( hc->altdir, &rest, 0, 1 );
+ if ( rest[0] != '\0' )
+ return 0;
+ httpd_realloc_str( &hc->altdir, &hc->maxaltdir, strlen( alt ) );
+ (void) strcpy( hc->altdir, alt );
+
+ /* And the filename becomes altdir plus the post-~ part of the original. */
+ httpd_realloc_str(
+ &hc->expnfilename, &hc->maxexpnfilename,
+ strlen( hc->altdir ) + 1 + strlen( cp ) );
+ (void) my_snprintf( hc->expnfilename, hc->maxexpnfilename,
+ "%s/%s", hc->altdir, cp );
+
+ /* For this type of tilde mapping, we want to defeat vhost mapping. */
+ hc->tildemapped = 1;
+
+ return 1;
+ }
+#endif /* TILDE_MAP_2 */
+
+
+/* Virtual host mapping. */
+static int
+vhost_map( httpd_conn* hc )
+ {
+ httpd_sockaddr sa;
+ socklen_t sz;
+ static char* tempfilename;
+ static size_t maxtempfilename = 0;
+ char* cp1;
+ int len;
+#ifdef VHOST_DIRLEVELS
+ int i;
+ char* cp2;
+#endif /* VHOST_DIRLEVELS */
+
+ /* Figure out the virtual hostname. */
+ if ( hc->reqhost[0] != '\0' )
+ hc->hostname = hc->reqhost;
+ else if ( hc->hdrhost[0] != '\0' )
+ hc->hostname = hc->hdrhost;
+ else
+ {
+ sz = sizeof(sa);
+ if ( getsockname( hc->conn_fd, &sa.sa, &sz ) < 0 )
+ {
+ syslog( LOG_ERR, "getsockname - %m" );
+ return 0;
+ }
+ hc->hostname = httpd_ntoa( &sa );
+ }
+ /* Pound it to lower case. */
+ for ( cp1 = hc->hostname; *cp1 != '\0'; ++cp1 )
+ if ( isupper( *cp1 ) )
+ *cp1 = tolower( *cp1 );
+
+ if ( hc->tildemapped )
+ return 1;
+
+ /* Figure out the host directory. */
+#ifdef VHOST_DIRLEVELS
+ httpd_realloc_str(
+ &hc->hostdir, &hc->maxhostdir,
+ strlen( hc->hostname ) + 2 * VHOST_DIRLEVELS );
+ if ( strncmp( hc->hostname, "www.", 4 ) == 0 )
+ cp1 = &hc->hostname[4];
+ else
+ cp1 = hc->hostname;
+ for ( cp2 = hc->hostdir, i = 0; i < VHOST_DIRLEVELS; ++i )
+ {
+ /* Skip dots in the hostname. If we don't, then we get vhost
+ ** directories in higher level of filestructure if dot gets
+ ** involved into path construction. It's `while' used here instead
+ ** of `if' for it's possible to have a hostname formed with two
+ ** dots at the end of it.
+ */
+ while ( *cp1 == '.' )
+ ++cp1;
+ /* Copy a character from the hostname, or '_' if we ran out. */
+ if ( *cp1 != '\0' )
+ *cp2++ = *cp1++;
+ else
+ *cp2++ = '_';
+ /* Copy a slash. */
+ *cp2++ = '/';
+ }
+ (void) strcpy( cp2, hc->hostname );
+#else /* VHOST_DIRLEVELS */
+ httpd_realloc_str( &hc->hostdir, &hc->maxhostdir, strlen( hc->hostname ) );
+ (void) strcpy( hc->hostdir, hc->hostname );
+#endif /* VHOST_DIRLEVELS */
+
+ /* Prepend hostdir to the filename. */
+ len = strlen( hc->expnfilename );
+ httpd_realloc_str( &tempfilename, &maxtempfilename, len );
+ (void) strcpy( tempfilename, hc->expnfilename );
+ httpd_realloc_str(
+ &hc->expnfilename, &hc->maxexpnfilename,
+ strlen( hc->hostdir ) + 1 + len );
+ (void) strcpy( hc->expnfilename, hc->hostdir );
+ (void) strcat( hc->expnfilename, "/" );
+ (void) strcat( hc->expnfilename, tempfilename );
+ return 1;
+ }
+
+
+/* Expands all symlinks in the given filename, eliding ..'s and leading /'s.
+** Returns the expanded path (pointer to static string), or (char*) 0 on
+** errors. Also returns, in the string pointed to by restP, any trailing
+** parts of the path that don't exist.
+**
+** This is a fairly nice little routine. It handles any size filenames
+** without excessive mallocs.
+*/
+static char*
+expand_symlinks( char* path, char** restP, int no_symlink_check, int tildemapped )
+ {
+ static char* checked;
+ static char* rest;
+ char lnk[5000];
+ static size_t maxchecked = 0, maxrest = 0;
+ size_t checkedlen, restlen, linklen, prevcheckedlen, prevrestlen;
+ int nlinks, i;
+ char* r;
+ char* cp1;
+ char* cp2;
+
+ if ( no_symlink_check )
+ {
+ /* If we are chrooted, we can actually skip the symlink-expansion,
+ ** since it's impossible to get out of the tree. However, we still
+ ** need to do the pathinfo check, and the existing symlink expansion
+ ** code is a pretty reasonable way to do this. So, what we do is
+ ** a single stat() of the whole filename - if it exists, then we
+ ** return it as is with nothing in restP. If it doesn't exist, we
+ ** fall through to the existing code.
+ **
+ ** One side-effect of this is that users can't symlink to central
+ ** approved CGIs any more. The workaround is to use the central
+ ** URL for the CGI instead of a local symlinked one.
+ */
+ struct stat sb;
+ if ( stat( path, &sb ) != -1 )
+ {
+ checkedlen = strlen( path );
+ httpd_realloc_str( &checked, &maxchecked, checkedlen );
+ (void) strcpy( checked, path );
+ /* Trim trailing slashes. */
+ while ( checked[checkedlen - 1] == '/' )
+ {
+ checked[checkedlen - 1] = '\0';
+ --checkedlen;
+ }
+ httpd_realloc_str( &rest, &maxrest, 0 );
+ rest[0] = '\0';
+ *restP = rest;
+ return checked;
+ }
+ }
+
+ /* Start out with nothing in checked and the whole filename in rest. */
+ httpd_realloc_str( &checked, &maxchecked, 1 );
+ checked[0] = '\0';
+ checkedlen = 0;
+ restlen = strlen( path );
+ httpd_realloc_str( &rest, &maxrest, restlen );
+ (void) strcpy( rest, path );
+ if ( rest[restlen - 1] == '/' )
+ rest[--restlen] = '\0'; /* trim trailing slash */
+ if ( ! tildemapped )
+ /* Remove any leading slashes. */
+ while ( rest[0] == '/' )
+ {
+ (void) ol_strcpy( rest, &(rest[1]) );
+ --restlen;
+ }
+ r = rest;
+ nlinks = 0;
+
+ /* While there are still components to check... */
+ while ( restlen > 0 )
+ {
+ /* Save current checkedlen in case we get a symlink. Save current
+ ** restlen in case we get a non-existant component.
+ */
+ prevcheckedlen = checkedlen;
+ prevrestlen = restlen;
+
+ /* Grab one component from r and transfer it to checked. */
+ cp1 = strchr( r, '/' );
+ if ( cp1 != (char*) 0 )
+ {
+ i = cp1 - r;
+ if ( i == 0 )
+ {
+ /* Special case for absolute paths. */
+ httpd_realloc_str( &checked, &maxchecked, checkedlen + 1 );
+ (void) strncpy( &checked[checkedlen], r, 1 );
+ checkedlen += 1;
+ }
+ else if ( strncmp( r, "..", MAX( i, 2 ) ) == 0 )
+ {
+ /* Ignore ..'s that go above the start of the path. */
+ if ( checkedlen != 0 )
+ {
+ cp2 = strrchr( checked, '/' );
+ if ( cp2 == (char*) 0 )
+ checkedlen = 0;
+ else if ( cp2 == checked )
+ checkedlen = 1;
+ else
+ checkedlen = cp2 - checked;
+ }
+ }
+ else
+ {
+ httpd_realloc_str( &checked, &maxchecked, checkedlen + 1 + i );
+ if ( checkedlen > 0 && checked[checkedlen-1] != '/' )
+ checked[checkedlen++] = '/';
+ (void) strncpy( &checked[checkedlen], r, i );
+ checkedlen += i;
+ }
+ checked[checkedlen] = '\0';
+ r += i + 1;
+ restlen -= i + 1;
+ }
+ else
+ {
+ /* No slashes remaining, r is all one component. */
+ if ( strcmp( r, ".." ) == 0 )
+ {
+ /* Ignore ..'s that go above the start of the path. */
+ if ( checkedlen != 0 )
+ {
+ cp2 = strrchr( checked, '/' );
+ if ( cp2 == (char*) 0 )
+ checkedlen = 0;
+ else if ( cp2 == checked )
+ checkedlen = 1;
+ else
+ checkedlen = cp2 - checked;
+ checked[checkedlen] = '\0';
+ }
+ }
+ else
+ {
+ httpd_realloc_str(
+ &checked, &maxchecked, checkedlen + 1 + restlen );
+ if ( checkedlen > 0 && checked[checkedlen-1] != '/' )
+ checked[checkedlen++] = '/';
+ (void) strcpy( &checked[checkedlen], r );
+ checkedlen += restlen;
+ }
+ r += restlen;
+ restlen = 0;
+ }
+
+ /* Try reading the current filename as a symlink */
+ if ( checked[0] == '\0' )
+ continue;
+ linklen = readlink( checked, lnk, sizeof(lnk) - 1 );
+ if ( linklen == -1 )
+ {
+ if ( errno == EINVAL )
+ continue; /* not a symlink */
+ if ( errno == EACCES || errno == ENOENT || errno == ENOTDIR )
+ {
+ /* That last component was bogus. Restore and return. */
+ *restP = r - ( prevrestlen - restlen );
+ if ( prevcheckedlen == 0 )
+ (void) strcpy( checked, "." );
+ else
+ checked[prevcheckedlen] = '\0';
+ return checked;
+ }
+ syslog( LOG_ERR, "readlink %.80s - %m", checked );
+ return (char*) 0;
+ }
+ ++nlinks;
+ if ( nlinks > MAX_LINKS )
+ {
+ syslog( LOG_ERR, "too many symlinks in %.80s", path );
+ return (char*) 0;
+ }
+ lnk[linklen] = '\0';
+ if ( lnk[linklen - 1] == '/' )
+ lnk[--linklen] = '\0'; /* trim trailing slash */
+
+ /* Insert the link contents in front of the rest of the filename. */
+ if ( restlen != 0 )
+ {
+ (void) ol_strcpy( rest, r );
+ httpd_realloc_str( &rest, &maxrest, restlen + linklen + 1 );
+ for ( i = restlen; i >= 0; --i )
+ rest[i + linklen + 1] = rest[i];
+ (void) strcpy( rest, lnk );
+ rest[linklen] = '/';
+ restlen += linklen + 1;
+ r = rest;
+ }
+ else
+ {
+ /* There's nothing left in the filename, so the link contents
+ ** becomes the rest.
+ */
+ httpd_realloc_str( &rest, &maxrest, linklen );
+ (void) strcpy( rest, lnk );
+ restlen = linklen;
+ r = rest;
+ }
+
+ if ( rest[0] == '/' )
+ {
+ /* There must have been an absolute symlink - zero out checked. */
+ checked[0] = '\0';
+ checkedlen = 0;
+ }
+ else
+ {
+ /* Re-check this component. */
+ checkedlen = prevcheckedlen;
+ checked[checkedlen] = '\0';
+ }
+ }
+
+ /* Ok. */
+ *restP = r;
+ if ( checked[0] == '\0' )
+ (void) strcpy( checked, "." );
+ return checked;
+ }
+
+
+int
+httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc )
+ {
+ httpd_sockaddr sa;
+ socklen_t sz;
+
+ if ( ! hc->initialized )
+ {
+ hc->read_size = 0;
+ httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 );
+ hc->maxdecodedurl =
+ hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings =
+ hc->maxpathinfo = hc->maxquery = hc->maxaccept =
+ hc->maxaccepte = hc->maxreqhost = hc->maxhostdir =
+ hc->maxremoteuser = hc->maxresponse = 0;
+#ifdef TILDE_MAP_2
+ hc->maxaltdir = 0;
+#endif /* TILDE_MAP_2 */
+ httpd_realloc_str( &hc->decodedurl, &hc->maxdecodedurl, 1 );
+ httpd_realloc_str( &hc->origfilename, &hc->maxorigfilename, 1 );
+ httpd_realloc_str( &hc->expnfilename, &hc->maxexpnfilename, 0 );
+ httpd_realloc_str( &hc->encodings, &hc->maxencodings, 0 );
+ httpd_realloc_str( &hc->pathinfo, &hc->maxpathinfo, 0 );
+ httpd_realloc_str( &hc->query, &hc->maxquery, 0 );
+ httpd_realloc_str( &hc->accept, &hc->maxaccept, 0 );
+ httpd_realloc_str( &hc->accepte, &hc->maxaccepte, 0 );
+ httpd_realloc_str( &hc->reqhost, &hc->maxreqhost, 0 );
+ httpd_realloc_str( &hc->hostdir, &hc->maxhostdir, 0 );
+ httpd_realloc_str( &hc->remoteuser, &hc->maxremoteuser, 0 );
+ httpd_realloc_str( &hc->response, &hc->maxresponse, 0 );
+#ifdef TILDE_MAP_2
+ httpd_realloc_str( &hc->altdir, &hc->maxaltdir, 0 );
+#endif /* TILDE_MAP_2 */
+ hc->initialized = 1;
+ }
+
+ /* Accept the new connection. */
+ sz = sizeof(sa);
+ hc->conn_fd = accept( listen_fd, &sa.sa, &sz );
+ if ( hc->conn_fd < 0 )
+ {
+ if ( errno == EWOULDBLOCK )
+ return GC_NO_MORE;
+ /* ECONNABORTED means the connection was closed by the client while
+ ** it was waiting in the listen queue. It's not worth logging.
+ */
+ if ( errno != ECONNABORTED )
+ syslog( LOG_ERR, "accept - %m" );
+ return GC_FAIL;
+ }
+ if ( ! sockaddr_check( &sa ) )
+ {
+ syslog( LOG_ERR, "unknown sockaddr family" );
+ close( hc->conn_fd );
+ hc->conn_fd = -1;
+ return GC_FAIL;
+ }
+ (void) fcntl( hc->conn_fd, F_SETFD, 1 );
+ hc->hs = hs;
+ (void) memset( &hc->client_addr, 0, sizeof(hc->client_addr) );
+ (void) memmove( &hc->client_addr, &sa, sockaddr_len( &sa ) );
+ hc->read_idx = 0;
+ hc->checked_idx = 0;
+ hc->checked_state = CHST_FIRSTWORD;
+ hc->method = METHOD_UNKNOWN;
+ hc->status = 0;
+ hc->bytes_to_send = 0;
+ hc->bytes_sent = 0;
+ hc->encodedurl = "";
+ hc->decodedurl[0] = '\0';
+ hc->protocol = "UNKNOWN";
+ hc->origfilename[0] = '\0';
+ hc->expnfilename[0] = '\0';
+ hc->encodings[0] = '\0';
+ hc->pathinfo[0] = '\0';
+ hc->query[0] = '\0';
+ hc->referrer = "";
+ hc->useragent = "";
+ hc->accept[0] = '\0';
+ hc->accepte[0] = '\0';
+ hc->acceptl = "";
+ hc->cookie = "";
+ hc->contenttype = "";
+ hc->reqhost[0] = '\0';
+ hc->hdrhost = "";
+ hc->hostdir[0] = '\0';
+ hc->authorization = "";
+ hc->remoteuser[0] = '\0';
+ hc->response[0] = '\0';
+#ifdef TILDE_MAP_2
+ hc->altdir[0] = '\0';
+#endif /* TILDE_MAP_2 */
+ hc->responselen = 0;
+ hc->if_modified_since = (time_t) -1;
+ hc->range_if = (time_t) -1;
+ hc->contentlength = -1;
+ hc->type = "";
+ hc->hostname = (char*) 0;
+ hc->mime_flag = 1;
+ hc->one_one = 0;
+ hc->got_range = 0;
+ hc->tildemapped = 0;
+ hc->first_byte_index = 0;
+ hc->last_byte_index = -1;
+ hc->keep_alive = 0;
+ hc->should_linger = 0;
+ hc->file_address = (char*) 0;
+ return GC_OK;
+ }
+
+
+/* Checks hc->read_buf to see whether a complete request has been read so far;
+** either the first line has two words (an HTTP/0.9 request), or the first
+** line has three words and there's a blank line present.
+**
+** hc->read_idx is how much has been read in; hc->checked_idx is how much we
+** have checked so far; and hc->checked_state is the current state of the
+** finite state machine.
+*/
+int
+httpd_got_request( httpd_conn* hc )
+ {
+ char c;
+
+ for ( ; hc->checked_idx < hc->read_idx; ++hc->checked_idx )
+ {
+ c = hc->read_buf[hc->checked_idx];
+ switch ( hc->checked_state )
+ {
+ case CHST_FIRSTWORD:
+ switch ( c )
+ {
+ case ' ': case '\t':
+ hc->checked_state = CHST_FIRSTWS;
+ break;
+ case '\012': case '\015':
+ hc->checked_state = CHST_BOGUS;
+ return GR_BAD_REQUEST;
+ }
+ break;
+ case CHST_FIRSTWS:
+ switch ( c )
+ {
+ case ' ': case '\t':
+ break;
+ case '\012': case '\015':
+ hc->checked_state = CHST_BOGUS;
+ return GR_BAD_REQUEST;
+ default:
+ hc->checked_state = CHST_SECONDWORD;
+ break;
+ }
+ break;
+ case CHST_SECONDWORD:
+ switch ( c )
+ {
+ case ' ': case '\t':
+ hc->checked_state = CHST_SECONDWS;
+ break;
+ case '\012': case '\015':
+ /* The first line has only two words - an HTTP/0.9 request. */
+ return GR_GOT_REQUEST;
+ }
+ break;
+ case CHST_SECONDWS:
+ switch ( c )
+ {
+ case ' ': case '\t':
+ break;
+ case '\012': case '\015':
+ hc->checked_state = CHST_BOGUS;
+ return GR_BAD_REQUEST;
+ default:
+ hc->checked_state = CHST_THIRDWORD;
+ break;
+ }
+ break;
+ case CHST_THIRDWORD:
+ switch ( c )
+ {
+ case ' ': case '\t':
+ hc->checked_state = CHST_THIRDWS;
+ break;
+ case '\012':
+ hc->checked_state = CHST_LF;
+ break;
+ case '\015':
+ hc->checked_state = CHST_CR;
+ break;
+ }
+ break;
+ case CHST_THIRDWS:
+ switch ( c )
+ {
+ case ' ': case '\t':
+ break;
+ case '\012':
+ hc->checked_state = CHST_LF;
+ break;
+ case '\015':
+ hc->checked_state = CHST_CR;
+ break;
+ default:
+ hc->checked_state = CHST_BOGUS;
+ return GR_BAD_REQUEST;
+ }
+ break;
+ case CHST_LINE:
+ switch ( c )
+ {
+ case '\012':
+ hc->checked_state = CHST_LF;
+ break;
+ case '\015':
+ hc->checked_state = CHST_CR;
+ break;
+ }
+ break;
+ case CHST_LF:
+ switch ( c )
+ {
+ case '\012':
+ /* Two newlines in a row - a blank line - end of request. */
+ return GR_GOT_REQUEST;
+ case '\015':
+ hc->checked_state = CHST_CR;
+ break;
+ default:
+ hc->checked_state = CHST_LINE;
+ break;
+ }
+ break;
+ case CHST_CR:
+ switch ( c )
+ {
+ case '\012':
+ hc->checked_state = CHST_CRLF;
+ break;
+ case '\015':
+ /* Two returns in a row - end of request. */
+ return GR_GOT_REQUEST;
+ default:
+ hc->checked_state = CHST_LINE;
+ break;
+ }
+ break;
+ case CHST_CRLF:
+ switch ( c )
+ {
+ case '\012':
+ /* Two newlines in a row - end of request. */
+ return GR_GOT_REQUEST;
+ case '\015':
+ hc->checked_state = CHST_CRLFCR;
+ break;
+ default:
+ hc->checked_state = CHST_LINE;
+ break;
+ }
+ break;
+ case CHST_CRLFCR:
+ switch ( c )
+ {
+ case '\012': case '\015':
+ /* Two CRLFs or two CRs in a row - end of request. */
+ return GR_GOT_REQUEST;
+ default:
+ hc->checked_state = CHST_LINE;
+ break;
+ }
+ break;
+ case CHST_BOGUS:
+ return GR_BAD_REQUEST;
+ }
+ }
+ return GR_NO_REQUEST;
+ }
+
+
+int
+httpd_parse_request( httpd_conn* hc )
+ {
+ char* buf;
+ char* method_str;
+ char* url;
+ char* protocol;
+ char* reqhost;
+ char* eol;
+ char* cp;
+ char* pi;
+
+ hc->checked_idx = 0; /* reset */
+ method_str = bufgets( hc );
+ url = strpbrk( method_str, " \t\012\015" );
+ if ( url == (char*) 0 )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+ *url++ = '\0';
+ url += strspn( url, " \t\012\015" );
+ protocol = strpbrk( url, " \t\012\015" );
+ if ( protocol == (char*) 0 )
+ {
+ protocol = "HTTP/0.9";
+ hc->mime_flag = 0;
+ }
+ else
+ {
+ *protocol++ = '\0';
+ protocol += strspn( protocol, " \t\012\015" );
+ if ( *protocol != '\0' )
+ {
+ eol = strpbrk( protocol, " \t\012\015" );
+ if ( eol != (char*) 0 )
+ *eol = '\0';
+ if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 )
+ hc->one_one = 1;
+ }
+ }
+ hc->protocol = protocol;
+
+ /* Check for HTTP/1.1 absolute URL. */
+ if ( strncasecmp( url, "http://", 7 ) == 0 )
+ {
+ if ( ! hc->one_one )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+ reqhost = url + 7;
+ url = strchr( reqhost, '/' );
+ if ( url == (char*) 0 )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+ *url = '\0';
+ if ( strchr( reqhost, '/' ) != (char*) 0 || reqhost[0] == '.' )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+ httpd_realloc_str( &hc->reqhost, &hc->maxreqhost, strlen( reqhost ) );
+ (void) strcpy( hc->reqhost, reqhost );
+ *url = '/';
+ }
+
+ if ( *url != '/' )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+
+ if ( strcasecmp( method_str, httpd_method_str( METHOD_GET ) ) == 0 )
+ hc->method = METHOD_GET;
+ else if ( strcasecmp( method_str, httpd_method_str( METHOD_HEAD ) ) == 0 )
+ hc->method = METHOD_HEAD;
+ else if ( strcasecmp( method_str, httpd_method_str( METHOD_POST ) ) == 0 )
+ hc->method = METHOD_POST;
+ else if ( strcasecmp( method_str, httpd_method_str( METHOD_PUT ) ) == 0 )
+ hc->method = METHOD_PUT;
+ else if ( strcasecmp( method_str, httpd_method_str( METHOD_DELETE ) ) == 0 )
+ hc->method = METHOD_DELETE;
+ else if ( strcasecmp( method_str, httpd_method_str( METHOD_TRACE ) ) == 0 )
+ hc->method = METHOD_TRACE;
+ else
+ {
+ httpd_send_err( hc, 501, err501title, "", err501form, method_str );
+ return -1;
+ }
+
+ hc->encodedurl = url;
+ httpd_realloc_str(
+ &hc->decodedurl, &hc->maxdecodedurl, strlen( hc->encodedurl ) );
+ strdecode( hc->decodedurl, hc->encodedurl );
+
+ httpd_realloc_str(
+ &hc->origfilename, &hc->maxorigfilename, strlen( hc->decodedurl ) );
+ (void) strcpy( hc->origfilename, &hc->decodedurl[1] );
+ /* Special case for top-level URL. */
+ if ( hc->origfilename[0] == '\0' )
+ (void) strcpy( hc->origfilename, "." );
+
+ /* Extract query string from encoded URL. */
+ cp = strchr( hc->encodedurl, '?' );
+ if ( cp != (char*) 0 )
+ {
+ ++cp;
+ httpd_realloc_str( &hc->query, &hc->maxquery, strlen( cp ) );
+ (void) strcpy( hc->query, cp );
+ /* Remove query from (decoded) origfilename. */
+ cp = strchr( hc->origfilename, '?' );
+ if ( cp != (char*) 0 )
+ *cp = '\0';
+ }
+
+ de_dotdot( hc->origfilename );
+ if ( hc->origfilename[0] == '/' ||
+ ( hc->origfilename[0] == '.' && hc->origfilename[1] == '.' &&
+ ( hc->origfilename[2] == '\0' || hc->origfilename[2] == '/' ) ) )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+
+ if ( hc->mime_flag )
+ {
+ /* Read the MIME headers. */
+ while ( ( buf = bufgets( hc ) ) != (char*) 0 )
+ {
+ if ( buf[0] == '\0' )
+ break;
+ if ( strncasecmp( buf, "Referer:", 8 ) == 0 )
+ {
+ cp = &buf[8];
+ cp += strspn( cp, " \t" );
+ hc->referrer = cp;
+ }
+ else if ( strncasecmp( buf, "Referrer:", 9 ) == 0 )
+ {
+ cp = &buf[9];
+ cp += strspn( cp, " \t" );
+ hc->referrer = cp;
+ }
+ else if ( strncasecmp( buf, "User-Agent:", 11 ) == 0 )
+ {
+ cp = &buf[11];
+ cp += strspn( cp, " \t" );
+ hc->useragent = cp;
+ }
+ else if ( strncasecmp( buf, "Host:", 5 ) == 0 )
+ {
+ cp = &buf[5];
+ cp += strspn( cp, " \t" );
+ hc->hdrhost = cp;
+ cp = strchr( hc->hdrhost, ':' );
+ if ( cp != (char*) 0 )
+ *cp = '\0';
+ if ( strchr( hc->hdrhost, '/' ) != (char*) 0 || hc->hdrhost[0] == '.' )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+ }
+ else if ( strncasecmp( buf, "Accept:", 7 ) == 0 )
+ {
+ cp = &buf[7];
+ cp += strspn( cp, " \t" );
+ if ( hc->accept[0] != '\0' )
+ {
+ if ( strlen( hc->accept ) > 5000 )
+ {
+ syslog(
+ LOG_ERR, "%.80s way too much Accept: data",
+ httpd_ntoa( &hc->client_addr ) );
+ continue;
+ }
+ httpd_realloc_str(
+ &hc->accept, &hc->maxaccept,
+ strlen( hc->accept ) + 2 + strlen( cp ) );
+ (void) strcat( hc->accept, ", " );
+ }
+ else
+ httpd_realloc_str(
+ &hc->accept, &hc->maxaccept, strlen( cp ) );
+ (void) strcat( hc->accept, cp );
+ }
+ else if ( strncasecmp( buf, "Accept-Encoding:", 16 ) == 0 )
+ {
+ cp = &buf[16];
+ cp += strspn( cp, " \t" );
+ if ( hc->accepte[0] != '\0' )
+ {
+ if ( strlen( hc->accepte ) > 5000 )
+ {
+ syslog(
+ LOG_ERR, "%.80s way too much Accept-Encoding: data",
+ httpd_ntoa( &hc->client_addr ) );
+ continue;
+ }
+ httpd_realloc_str(
+ &hc->accepte, &hc->maxaccepte,
+ strlen( hc->accepte ) + 2 + strlen( cp ) );
+ (void) strcat( hc->accepte, ", " );
+ }
+ else
+ httpd_realloc_str(
+ &hc->accepte, &hc->maxaccepte, strlen( cp ) );
+ (void) strcpy( hc->accepte, cp );
+ }
+ else if ( strncasecmp( buf, "Accept-Language:", 16 ) == 0 )
+ {
+ cp = &buf[16];
+ cp += strspn( cp, " \t" );
+ hc->acceptl = cp;
+ }
+ else if ( strncasecmp( buf, "If-Modified-Since:", 18 ) == 0 )
+ {
+ cp = &buf[18];
+ hc->if_modified_since = tdate_parse( cp );
+ if ( hc->if_modified_since == (time_t) -1 )
+ syslog( LOG_DEBUG, "unparsable time: %.80s", cp );
+ }
+ else if ( strncasecmp( buf, "Cookie:", 7 ) == 0 )
+ {
+ cp = &buf[7];
+ cp += strspn( cp, " \t" );
+ hc->cookie = cp;
+ }
+ else if ( strncasecmp( buf, "Range:", 6 ) == 0 )
+ {
+ /* Only support %d- and %d-%d, not %d-%d,%d-%d or -%d. */
+ if ( strchr( buf, ',' ) == (char*) 0 )
+ {
+ char* cp_dash;
+ cp = strpbrk( buf, "=" );
+ if ( cp != (char*) 0 )
+ {
+ cp_dash = strchr( cp + 1, '-' );
+ if ( cp_dash != (char*) 0 && cp_dash != cp + 1 )
+ {
+ *cp_dash = '\0';
+ hc->got_range = 1;
+ hc->first_byte_index = atoll( cp + 1 );
+ if ( hc->first_byte_index < 0 )
+ hc->first_byte_index = 0;
+ if ( isdigit( (int) cp_dash[1] ) )
+ {
+ hc->last_byte_index = atoll( cp_dash + 1 );
+ if ( hc->last_byte_index < 0 )
+ hc->last_byte_index = -1;
+ }
+ }
+ }
+ }
+ }
+ else if ( strncasecmp( buf, "Range-If:", 9 ) == 0 ||
+ strncasecmp( buf, "If-Range:", 9 ) == 0 )
+ {
+ cp = &buf[9];
+ hc->range_if = tdate_parse( cp );
+ if ( hc->range_if == (time_t) -1 )
+ syslog( LOG_DEBUG, "unparsable time: %.80s", cp );
+ }
+ else if ( strncasecmp( buf, "Content-Type:", 13 ) == 0 )
+ {
+ cp = &buf[13];
+ cp += strspn( cp, " \t" );
+ hc->contenttype = cp;
+ }
+ else if ( strncasecmp( buf, "Content-Length:", 15 ) == 0 )
+ {
+ cp = &buf[15];
+ hc->contentlength = atol( cp );
+ }
+ else if ( strncasecmp( buf, "Authorization:", 14 ) == 0 )
+ {
+ cp = &buf[14];
+ cp += strspn( cp, " \t" );
+ hc->authorization = cp;
+ }
+ else if ( strncasecmp( buf, "Connection:", 11 ) == 0 )
+ {
+ cp = &buf[11];
+ cp += strspn( cp, " \t" );
+ if ( strcasecmp( cp, "keep-alive" ) == 0 )
+ hc->keep_alive = 1;
+ }
+#ifdef LOG_UNKNOWN_HEADERS
+ else if ( strncasecmp( buf, "Accept-Charset:", 15 ) == 0 ||
+ strncasecmp( buf, "Accept-Language:", 16 ) == 0 ||
+ strncasecmp( buf, "Agent:", 6 ) == 0 ||
+ strncasecmp( buf, "Cache-Control:", 14 ) == 0 ||
+ strncasecmp( buf, "Cache-Info:", 11 ) == 0 ||
+ strncasecmp( buf, "Charge-To:", 10 ) == 0 ||
+ strncasecmp( buf, "Client-IP:", 10 ) == 0 ||
+ strncasecmp( buf, "Date:", 5 ) == 0 ||
+ strncasecmp( buf, "Extension:", 10 ) == 0 ||
+ strncasecmp( buf, "Forwarded:", 10 ) == 0 ||
+ strncasecmp( buf, "From:", 5 ) == 0 ||
+ strncasecmp( buf, "HTTP-Version:", 13 ) == 0 ||
+ strncasecmp( buf, "Max-Forwards:", 13 ) == 0 ||
+ strncasecmp( buf, "Message-Id:", 11 ) == 0 ||
+ strncasecmp( buf, "MIME-Version:", 13 ) == 0 ||
+ strncasecmp( buf, "Negotiate:", 10 ) == 0 ||
+ strncasecmp( buf, "Pragma:", 7 ) == 0 ||
+ strncasecmp( buf, "Proxy-Agent:", 12 ) == 0 ||
+ strncasecmp( buf, "Proxy-Connection:", 17 ) == 0 ||
+ strncasecmp( buf, "Security-Scheme:", 16 ) == 0 ||
+ strncasecmp( buf, "Session-Id:", 11 ) == 0 ||
+ strncasecmp( buf, "UA-Color:", 9 ) == 0 ||
+ strncasecmp( buf, "UA-CPU:", 7 ) == 0 ||
+ strncasecmp( buf, "UA-Disp:", 8 ) == 0 ||
+ strncasecmp( buf, "UA-OS:", 6 ) == 0 ||
+ strncasecmp( buf, "UA-Pixels:", 10 ) == 0 ||
+ strncasecmp( buf, "User:", 5 ) == 0 ||
+ strncasecmp( buf, "Via:", 4 ) == 0 ||
+ strncasecmp( buf, "X-", 2 ) == 0 )
+ ; /* ignore */
+ else
+ syslog( LOG_DEBUG, "unknown request header: %.80s", buf );
+#endif /* LOG_UNKNOWN_HEADERS */
+ }
+ }
+
+ if ( hc->one_one )
+ {
+ /* Check that HTTP/1.1 requests specify a host, as required. */
+ if ( hc->reqhost[0] == '\0' && hc->hdrhost[0] == '\0' )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ return -1;
+ }
+
+ /* If the client wants to do keep-alives, it might also be doing
+ ** pipelining. There's no way for us to tell. Since we don't
+ ** implement keep-alives yet, if we close such a connection there
+ ** might be unread pipelined requests waiting. So, we have to
+ ** do a lingering close.
+ */
+ if ( hc->keep_alive )
+ hc->should_linger = 1;
+ }
+
+ /* Ok, the request has been parsed. Now we resolve stuff that
+ ** may require the entire request.
+ */
+
+ /* Copy original filename to expanded filename. */
+ httpd_realloc_str(
+ &hc->expnfilename, &hc->maxexpnfilename, strlen( hc->origfilename ) );
+ (void) strcpy( hc->expnfilename, hc->origfilename );
+
+ /* Tilde mapping. */
+ if ( hc->expnfilename[0] == '~' )
+ {
+#ifdef TILDE_MAP_1
+ if ( ! tilde_map_1( hc ) )
+ {
+ httpd_send_err( hc, 404, err404title, "", err404form, hc->encodedurl );
+ return -1;
+ }
+#endif /* TILDE_MAP_1 */
+#ifdef TILDE_MAP_2
+ if ( ! tilde_map_2( hc ) )
+ {
+ httpd_send_err( hc, 404, err404title, "", err404form, hc->encodedurl );
+ return -1;
+ }
+#endif /* TILDE_MAP_2 */
+ }
+
+ /* Virtual host mapping. */
+ if ( hc->hs->vhost )
+ if ( ! vhost_map( hc ) )
+ {
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ return -1;
+ }
+
+ /* Expand all symbolic links in the filename. This also gives us
+ ** any trailing non-existing components, for pathinfo.
+ */
+ cp = expand_symlinks( hc->expnfilename, &pi, hc->hs->no_symlink_check, hc->tildemapped );
+ if ( cp == (char*) 0 )
+ {
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ return -1;
+ }
+ httpd_realloc_str( &hc->expnfilename, &hc->maxexpnfilename, strlen( cp ) );
+ (void) strcpy( hc->expnfilename, cp );
+ httpd_realloc_str( &hc->pathinfo, &hc->maxpathinfo, strlen( pi ) );
+ (void) strcpy( hc->pathinfo, pi );
+
+ /* Remove pathinfo stuff from the original filename too. */
+ if ( hc->pathinfo[0] != '\0' )
+ {
+ int i;
+ i = strlen( hc->origfilename ) - strlen( hc->pathinfo );
+ if ( i > 0 && strcmp( &hc->origfilename[i], hc->pathinfo ) == 0 )
+ hc->origfilename[i - 1] = '\0';
+ }
+
+ /* If the expanded filename is an absolute path, check that it's still
+ ** within the current directory or the alternate directory.
+ */
+ if ( hc->expnfilename[0] == '/' )
+ {
+ if ( strncmp(
+ hc->expnfilename, hc->hs->cwd, strlen( hc->hs->cwd ) ) == 0 )
+ {
+ /* Elide the current directory. */
+ (void) ol_strcpy(
+ hc->expnfilename, &hc->expnfilename[strlen( hc->hs->cwd )] );
+ }
+#ifdef TILDE_MAP_2
+ else if ( hc->altdir[0] != '\0' &&
+ ( strncmp(
+ hc->expnfilename, hc->altdir,
+ strlen( hc->altdir ) ) == 0 &&
+ ( hc->expnfilename[strlen( hc->altdir )] == '\0' ||
+ hc->expnfilename[strlen( hc->altdir )] == '/' ) ) )
+ {}
+#endif /* TILDE_MAP_2 */
+ else
+ {
+ syslog(
+ LOG_NOTICE, "%.80s URL \"%.80s\" goes outside the web tree",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' resolves to a file outside the permitted web server directory tree.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+
+static char*
+bufgets( httpd_conn* hc )
+ {
+ int i;
+ char c;
+
+ for ( i = hc->checked_idx; hc->checked_idx < hc->read_idx; ++hc->checked_idx )
+ {
+ c = hc->read_buf[hc->checked_idx];
+ if ( c == '\012' || c == '\015' )
+ {
+ hc->read_buf[hc->checked_idx] = '\0';
+ ++hc->checked_idx;
+ if ( c == '\015' && hc->checked_idx < hc->read_idx &&
+ hc->read_buf[hc->checked_idx] == '\012' )
+ {
+ hc->read_buf[hc->checked_idx] = '\0';
+ ++hc->checked_idx;
+ }
+ return &(hc->read_buf[i]);
+ }
+ }
+ return (char*) 0;
+ }
+
+
+static void
+de_dotdot( char* file )
+ {
+ char* cp;
+ char* cp2;
+ int l;
+
+ /* Collapse any multiple / sequences. */
+ while ( ( cp = strstr( file, "//") ) != (char*) 0 )
+ {
+ for ( cp2 = cp + 2; *cp2 == '/'; ++cp2 )
+ continue;
+ (void) ol_strcpy( cp + 1, cp2 );
+ }
+
+ /* Remove leading ./ and any /./ sequences. */
+ while ( strncmp( file, "./", 2 ) == 0 )
+ (void) ol_strcpy( file, file + 2 );
+ while ( ( cp = strstr( file, "/./") ) != (char*) 0 )
+ (void) ol_strcpy( cp, cp + 2 );
+
+ /* Alternate between removing leading ../ and removing xxx/../ */
+ for (;;)
+ {
+ while ( strncmp( file, "../", 3 ) == 0 )
+ (void) ol_strcpy( file, file + 3 );
+ cp = strstr( file, "/../" );
+ if ( cp == (char*) 0 )
+ break;
+ for ( cp2 = cp - 1; cp2 >= file && *cp2 != '/'; --cp2 )
+ continue;
+ (void) ol_strcpy( cp2 + 1, cp + 4 );
+ }
+
+ /* Also elide any xxx/.. at the end. */
+ while ( ( l = strlen( file ) ) > 3 &&
+ strcmp( ( cp = file + l - 3 ), "/.." ) == 0 )
+ {
+ for ( cp2 = cp - 1; cp2 >= file && *cp2 != '/'; --cp2 )
+ continue;
+ if ( cp2 < file )
+ break;
+ *cp2 = '\0';
+ }
+ }
+
+
+void
+httpd_close_conn( httpd_conn* hc, struct timeval* nowP )
+ {
+ make_log_entry( hc, nowP );
+
+ if ( hc->file_address != (char*) 0 )
+ {
+ mmc_unmap( hc->file_address, &(hc->sb), nowP );
+ hc->file_address = (char*) 0;
+ }
+ if ( hc->conn_fd >= 0 )
+ {
+ (void) close( hc->conn_fd );
+ hc->conn_fd = -1;
+ }
+ }
+
+void
+httpd_destroy_conn( httpd_conn* hc )
+ {
+ if ( hc->initialized )
+ {
+ free( (void*) hc->read_buf );
+ free( (void*) hc->decodedurl );
+ free( (void*) hc->origfilename );
+ free( (void*) hc->expnfilename );
+ free( (void*) hc->encodings );
+ free( (void*) hc->pathinfo );
+ free( (void*) hc->query );
+ free( (void*) hc->accept );
+ free( (void*) hc->accepte );
+ free( (void*) hc->reqhost );
+ free( (void*) hc->hostdir );
+ free( (void*) hc->remoteuser );
+ free( (void*) hc->response );
+#ifdef TILDE_MAP_2
+ free( (void*) hc->altdir );
+#endif /* TILDE_MAP_2 */
+ hc->initialized = 0;
+ }
+ }
+
+
+struct mime_entry {
+ char* ext;
+ size_t ext_len;
+ char* val;
+ size_t val_len;
+ };
+static struct mime_entry enc_tab[] = {
+#include "mime_encodings.h"
+ };
+static const int n_enc_tab = sizeof(enc_tab) / sizeof(*enc_tab);
+static struct mime_entry typ_tab[] = {
+#include "mime_types.h"
+ };
+static const int n_typ_tab = sizeof(typ_tab) / sizeof(*typ_tab);
+
+
+/* qsort comparison routine */
+static int
+ext_compare( const void* v1, const void* v2 )
+ {
+ const struct mime_entry* m1 = (const struct mime_entry*) v1;
+ const struct mime_entry* m2 = (const struct mime_entry*) v2;
+
+ return strcmp( m1->ext, m2->ext );
+ }
+
+
+static void
+init_mime( void )
+ {
+ int i;
+
+ /* Sort the tables so we can do binary search. */
+ qsort( enc_tab, n_enc_tab, sizeof(*enc_tab), ext_compare );
+ qsort( typ_tab, n_typ_tab, sizeof(*typ_tab), ext_compare );
+
+ /* Fill in the lengths. */
+ for ( i = 0; i < n_enc_tab; ++i )
+ {
+ enc_tab[i].ext_len = strlen( enc_tab[i].ext );
+ enc_tab[i].val_len = strlen( enc_tab[i].val );
+ }
+ for ( i = 0; i < n_typ_tab; ++i )
+ {
+ typ_tab[i].ext_len = strlen( typ_tab[i].ext );
+ typ_tab[i].val_len = strlen( typ_tab[i].val );
+ }
+
+ }
+
+
+/* Figure out MIME encodings and type based on the filename. Multiple
+** encodings are separated by commas, and are listed in the order in
+** which they were applied to the file.
+*/
+static void
+figure_mime( httpd_conn* hc )
+ {
+ char* prev_dot;
+ char* dot;
+ char* ext;
+ int me_indexes[100], n_me_indexes;
+ size_t ext_len, encodings_len;
+ int i, top, bot, mid;
+ int r;
+ char* default_type = "text/plain; charset=%s";
+
+ /* Peel off encoding extensions until there aren't any more. */
+ n_me_indexes = 0;
+ for ( prev_dot = &hc->expnfilename[strlen(hc->expnfilename)]; ; prev_dot = dot )
+ {
+ for ( dot = prev_dot - 1; dot >= hc->expnfilename && *dot != '.'; --dot )
+ ;
+ if ( dot < hc->expnfilename )
+ {
+ /* No dot found. No more encoding extensions, and no type
+ ** extension either.
+ */
+ hc->type = default_type;
+ goto done;
+ }
+ ext = dot + 1;
+ ext_len = prev_dot - ext;
+ /* Search the encodings table. Linear search is fine here, there
+ ** are only a few entries.
+ */
+ for ( i = 0; i < n_enc_tab; ++i )
+ {
+ if ( ext_len == enc_tab[i].ext_len && strncasecmp( ext, enc_tab[i].ext, ext_len ) == 0 )
+ {
+ if ( n_me_indexes < sizeof(me_indexes)/sizeof(*me_indexes) )
+ {
+ me_indexes[n_me_indexes] = i;
+ ++n_me_indexes;
+ }
+ goto next;
+ }
+ }
+ /* No encoding extension found. Break and look for a type extension. */
+ break;
+
+ next: ;
+ }
+
+ /* Binary search for a matching type extension. */
+ top = n_typ_tab - 1;
+ bot = 0;
+ while ( top >= bot )
+ {
+ mid = ( top + bot ) / 2;
+ r = strncasecmp( ext, typ_tab[mid].ext, ext_len );
+ if ( r < 0 )
+ top = mid - 1;
+ else if ( r > 0 )
+ bot = mid + 1;
+ else
+ if ( ext_len < typ_tab[mid].ext_len )
+ top = mid - 1;
+ else if ( ext_len > typ_tab[mid].ext_len )
+ bot = mid + 1;
+ else
+ {
+ hc->type = typ_tab[mid].val;
+ goto done;
+ }
+ }
+ hc->type = default_type;
+
+ done:
+
+ /* The last thing we do is actually generate the mime-encoding header. */
+ hc->encodings[0] = '\0';
+ encodings_len = 0;
+ for ( i = n_me_indexes - 1; i >= 0; --i )
+ {
+ httpd_realloc_str(
+ &hc->encodings, &hc->maxencodings,
+ encodings_len + enc_tab[me_indexes[i]].val_len + 1 );
+ if ( hc->encodings[0] != '\0' )
+ {
+ (void) strcpy( &hc->encodings[encodings_len], "," );
+ ++encodings_len;
+ }
+ (void) strcpy( &hc->encodings[encodings_len], enc_tab[me_indexes[i]].val );
+ encodings_len += enc_tab[me_indexes[i]].val_len;
+ }
+
+ }
+
+
+#ifdef CGI_TIMELIMIT
+static void
+cgi_kill2( ClientData client_data, struct timeval* nowP )
+ {
+ pid_t pid;
+
+ pid = (pid_t) client_data.i;
+ if ( kill( pid, SIGKILL ) == 0 )
+ syslog( LOG_WARNING, "hard-killed CGI process %d", pid );
+ }
+
+static void
+cgi_kill( ClientData client_data, struct timeval* nowP )
+ {
+ pid_t pid;
+
+ pid = (pid_t) client_data.i;
+ if ( kill( pid, SIGINT ) == 0 )
+ {
+ syslog( LOG_WARNING, "killed CGI process %d", pid );
+ /* In case this isn't enough, schedule an uncatchable kill. */
+ if ( tmr_create( nowP, cgi_kill2, client_data, 5 * 1000L, 0 ) == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(cgi_kill2) failed" );
+ exit( 1 );
+ }
+ }
+ }
+#endif /* CGI_TIMELIMIT */
+
+
+#ifdef GENERATE_INDEXES
+
+/* qsort comparison routine */
+static int
+name_compare( const void* v1, const void* v2 )
+ {
+ const char** c1 = (const char**) v1;
+ const char** c2 = (const char**) v2;
+ return strcmp( *c1, *c2 );
+ }
+
+
+static int
+ls( httpd_conn* hc )
+ {
+ DIR* dirp;
+ struct dirent* de;
+ int namlen;
+ static int maxnames = 0;
+ int nnames;
+ static char* names;
+ static char** nameptrs;
+ static char* name;
+ static size_t maxname = 0;
+ static char* rname;
+ static size_t maxrname = 0;
+ static char* encrname;
+ static size_t maxencrname = 0;
+ FILE* fp;
+ int i, r;
+ struct stat sb;
+ struct stat lsb;
+ char modestr[20];
+ char* linkprefix;
+ char lnk[MAXPATHLEN+1];
+ int linklen;
+ char* fileclass;
+ time_t now;
+ char* timestr;
+ ClientData client_data;
+
+ dirp = opendir( hc->expnfilename );
+ if ( dirp == (DIR*) 0 )
+ {
+ syslog( LOG_ERR, "opendir %.80s - %m", hc->expnfilename );
+ httpd_send_err( hc, 404, err404title, "", err404form, hc->encodedurl );
+ return -1;
+ }
+
+ if ( hc->method == METHOD_HEAD )
+ {
+ closedir( dirp );
+ send_mime(
+ hc, 200, ok200title, "", "", "text/html; charset=%s", (off_t) -1,
+ hc->sb.st_mtime );
+ }
+ else if ( hc->method == METHOD_GET )
+ {
+ if ( hc->hs->cgi_limit != 0 && hc->hs->cgi_count >= hc->hs->cgi_limit )
+ {
+ closedir( dirp );
+ httpd_send_err(
+ hc, 503, httpd_err503title, "", httpd_err503form,
+ hc->encodedurl );
+ return -1;
+ }
+ ++hc->hs->cgi_count;
+ r = fork( );
+ if ( r < 0 )
+ {
+ syslog( LOG_ERR, "fork - %m" );
+ closedir( dirp );
+ httpd_send_err(
+ hc, 500, err500title, "", err500form, hc->encodedurl );
+ return -1;
+ }
+ if ( r == 0 )
+ {
+ /* Child process. */
+ sub_process = 1;
+ httpd_unlisten( hc->hs );
+ send_mime(
+ hc, 200, ok200title, "", "", "text/html; charset=%s",
+ (off_t) -1, hc->sb.st_mtime );
+ httpd_write_response( hc );
+
+#ifdef CGI_NICE
+ /* Set priority. */
+ (void) nice( CGI_NICE );
+#endif /* CGI_NICE */
+
+ /* Open a stdio stream so that we can use fprintf, which is more
+ ** efficient than a bunch of separate write()s. We don't have
+ ** to worry about double closes or file descriptor leaks cause
+ ** we're in a subprocess.
+ */
+ fp = fdopen( hc->conn_fd, "w" );
+ if ( fp == (FILE*) 0 )
+ {
+ syslog( LOG_ERR, "fdopen - %m" );
+ httpd_send_err(
+ hc, 500, err500title, "", err500form, hc->encodedurl );
+ httpd_write_response( hc );
+ closedir( dirp );
+ exit( 1 );
+ }
+
+ (void) fprintf( fp, "\
+<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n\
+\n\
+<html>\n\
+\n\
+ <head>\n\
+ <meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\">\n\
+ <title>Index of %.80s</title>\n\
+ </head>\n\
+\n\
+ <body bgcolor=\"#99cc99\" text=\"#000000\" link=\"#2020ff\" vlink=\"#4040cc\">\n\
+\n\
+ <h2>Index of %.80s</h2>\n\
+\n\
+ <pre>\n\
+mode links bytes last-changed name\n\
+ <hr>",
+ hc->encodedurl, hc->encodedurl );
+
+ /* Read in names. */
+ nnames = 0;
+ while ( ( de = readdir( dirp ) ) != 0 ) /* dirent or direct */
+ {
+ if ( nnames >= maxnames )
+ {
+ if ( maxnames == 0 )
+ {
+ maxnames = 100;
+ names = NEW( char, maxnames * ( MAXPATHLEN + 1 ) );
+ nameptrs = NEW( char*, maxnames );
+ }
+ else
+ {
+ maxnames *= 2;
+ names = RENEW( names, char, maxnames * ( MAXPATHLEN + 1 ) );
+ nameptrs = RENEW( nameptrs, char*, maxnames );
+ }
+ if ( names == (char*) 0 || nameptrs == (char**) 0 )
+ {
+ syslog( LOG_ERR, "out of memory reallocating directory names" );
+ exit( 1 );
+ }
+ for ( i = 0; i < maxnames; ++i )
+ nameptrs[i] = &names[i * ( MAXPATHLEN + 1 )];
+ }
+ namlen = NAMLEN(de);
+ (void) strncpy( nameptrs[nnames], de->d_name, namlen );
+ nameptrs[nnames][namlen] = '\0';
+ ++nnames;
+ }
+ closedir( dirp );
+
+ /* Sort the names. */
+ qsort( nameptrs, nnames, sizeof(*nameptrs), name_compare );
+
+ /* Generate output. */
+ for ( i = 0; i < nnames; ++i )
+ {
+ httpd_realloc_str(
+ &name, &maxname,
+ strlen( hc->expnfilename ) + 1 + strlen( nameptrs[i] ) );
+ httpd_realloc_str(
+ &rname, &maxrname,
+ strlen( hc->origfilename ) + 1 + strlen( nameptrs[i] ) );
+ if ( hc->expnfilename[0] == '\0' ||
+ strcmp( hc->expnfilename, "." ) == 0 )
+ {
+ (void) strcpy( name, nameptrs[i] );
+ (void) strcpy( rname, nameptrs[i] );
+ }
+ else
+ {
+ (void) my_snprintf( name, maxname,
+ "%s/%s", hc->expnfilename, nameptrs[i] );
+ if ( strcmp( hc->origfilename, "." ) == 0 )
+ (void) my_snprintf( rname, maxrname,
+ "%s", nameptrs[i] );
+ else
+ (void) my_snprintf( rname, maxrname,
+ "%s%s", hc->origfilename, nameptrs[i] );
+ }
+ httpd_realloc_str(
+ &encrname, &maxencrname, 3 * strlen( rname ) + 1 );
+ strencode( encrname, maxencrname, rname );
+
+ if ( stat( name, &sb ) < 0 || lstat( name, &lsb ) < 0 )
+ continue;
+
+ linkprefix = "";
+ lnk[0] = '\0';
+ /* Break down mode word. First the file type. */
+ switch ( lsb.st_mode & S_IFMT )
+ {
+ case S_IFIFO: modestr[0] = 'p'; break;
+ case S_IFCHR: modestr[0] = 'c'; break;
+ case S_IFDIR: modestr[0] = 'd'; break;
+ case S_IFBLK: modestr[0] = 'b'; break;
+ case S_IFREG: modestr[0] = '-'; break;
+ case S_IFSOCK: modestr[0] = 's'; break;
+ case S_IFLNK: modestr[0] = 'l';
+ linklen = readlink( name, lnk, sizeof(lnk) - 1 );
+ if ( linklen != -1 )
+ {
+ lnk[linklen] = '\0';
+ linkprefix = " -> ";
+ }
+ break;
+ default: modestr[0] = '?'; break;
+ }
+ /* Now the world permissions. Owner and group permissions
+ ** are not of interest to web clients.
+ */
+ modestr[1] = ( lsb.st_mode & S_IROTH ) ? 'r' : '-';
+ modestr[2] = ( lsb.st_mode & S_IWOTH ) ? 'w' : '-';
+ modestr[3] = ( lsb.st_mode & S_IXOTH ) ? 'x' : '-';
+ modestr[4] = '\0';
+
+ /* We also leave out the owner and group name, they are
+ ** also not of interest to web clients. Plus if we're
+ ** running under chroot(), they would require a copy
+ ** of /etc/passwd and /etc/group, which we want to avoid.
+ */
+
+ /* Get time string. */
+ now = time( (time_t*) 0 );
+ timestr = ctime( &lsb.st_mtime );
+ timestr[ 0] = timestr[ 4];
+ timestr[ 1] = timestr[ 5];
+ timestr[ 2] = timestr[ 6];
+ timestr[ 3] = ' ';
+ timestr[ 4] = timestr[ 8];
+ timestr[ 5] = timestr[ 9];
+ timestr[ 6] = ' ';
+ if ( now - lsb.st_mtime > 60*60*24*182 ) /* 1/2 year */
+ {
+ timestr[ 7] = ' ';
+ timestr[ 8] = timestr[20];
+ timestr[ 9] = timestr[21];
+ timestr[10] = timestr[22];
+ timestr[11] = timestr[23];
+ }
+ else
+ {
+ timestr[ 7] = timestr[11];
+ timestr[ 8] = timestr[12];
+ timestr[ 9] = ':';
+ timestr[10] = timestr[14];
+ timestr[11] = timestr[15];
+ }
+ timestr[12] = '\0';
+
+ /* The ls -F file class. */
+ switch ( sb.st_mode & S_IFMT )
+ {
+ case S_IFDIR: fileclass = "/"; break;
+ case S_IFSOCK: fileclass = "="; break;
+ case S_IFLNK: fileclass = "@"; break;
+ default:
+ fileclass = ( sb.st_mode & S_IXOTH ) ? "*" : "";
+ break;
+ }
+
+ /* And print. */
+ (void) fprintf( fp,
+ "%s %3ld %10lld %s <a href=\"/%.500s%s\">%.80s</a>%s%s%s\n",
+ modestr, (long) lsb.st_nlink, (long long) lsb.st_size,
+ timestr, encrname, S_ISDIR(sb.st_mode) ? "/" : "",
+ nameptrs[i], linkprefix, lnk, fileclass );
+ }
+
+ (void) fprintf( fp, " </pre>\n </body>\n</html>\n" );
+ (void) fclose( fp );
+ exit( 0 );
+ }
+
+ /* Parent process. */
+ closedir( dirp );
+ syslog( LOG_DEBUG, "spawned indexing process %d for directory '%.200s'", r, hc->expnfilename );
+#ifdef CGI_TIMELIMIT
+ /* Schedule a kill for the child process, in case it runs too long */
+ client_data.i = r;
+ if ( tmr_create( (struct timeval*) 0, cgi_kill, client_data, CGI_TIMELIMIT * 1000L, 0 ) == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(cgi_kill ls) failed" );
+ exit( 1 );
+ }
+#endif /* CGI_TIMELIMIT */
+ hc->status = 200;
+ hc->bytes_sent = CGI_BYTECOUNT;
+ hc->should_linger = 0;
+ }
+ else
+ {
+ closedir( dirp );
+ httpd_send_err(
+ hc, 501, err501title, "", err501form, httpd_method_str( hc->method ) );
+ return -1;
+ }
+
+ return 0;
+ }
+
+#endif /* GENERATE_INDEXES */
+
+
+static char*
+build_env( char* fmt, char* arg )
+ {
+ char* cp;
+ size_t size;
+ static char* buf;
+ static size_t maxbuf = 0;
+
+ size = strlen( fmt ) + strlen( arg );
+ if ( size > maxbuf )
+ httpd_realloc_str( &buf, &maxbuf, size );
+ (void) my_snprintf( buf, maxbuf, fmt, arg );
+ cp = strdup( buf );
+ if ( cp == (char*) 0 )
+ {
+ syslog( LOG_ERR, "out of memory copying environment variable" );
+ exit( 1 );
+ }
+ return cp;
+ }
+
+
+#ifdef SERVER_NAME_LIST
+static char*
+hostname_map( char* hostname )
+ {
+ int len, n;
+ static char* list[] = { SERVER_NAME_LIST };
+
+ len = strlen( hostname );
+ for ( n = sizeof(list) / sizeof(*list) - 1; n >= 0; --n )
+ if ( strncasecmp( hostname, list[n], len ) == 0 )
+ if ( list[n][len] == '/' ) /* check in case of a substring match */
+ return &list[n][len + 1];
+ return (char*) 0;
+ }
+#endif /* SERVER_NAME_LIST */
+
+
+/* Set up environment variables. Be real careful here to avoid
+** letting malicious clients overrun a buffer. We don't have
+** to worry about freeing stuff since we're a sub-process.
+*/
+static char**
+make_envp( httpd_conn* hc )
+ {
+ static char* envp[50];
+ int envn;
+ char* cp;
+ char buf[256];
+
+ envn = 0;
+ envp[envn++] = build_env( "PATH=%s", CGI_PATH );
+#ifdef CGI_LD_LIBRARY_PATH
+ envp[envn++] = build_env( "LD_LIBRARY_PATH=%s", CGI_LD_LIBRARY_PATH );
+#endif /* CGI_LD_LIBRARY_PATH */
+ envp[envn++] = build_env( "SERVER_SOFTWARE=%s", SERVER_SOFTWARE );
+ if ( hc->hs->vhost && hc->hostname != (char*) 0 && hc->hostname[0] != '\0' )
+ cp = hc->hostname;
+ else if ( hc->hdrhost != (char*) 0 && hc->hdrhost[0] != '\0' )
+ cp = hc->hdrhost;
+ else if ( hc->reqhost != (char*) 0 && hc->reqhost[0] != '\0' )
+ cp = hc->reqhost;
+ else
+ cp = hc->hs->server_hostname;
+ if ( cp != (char*) 0 )
+ envp[envn++] = build_env( "SERVER_NAME=%s", cp );
+ envp[envn++] = "GATEWAY_INTERFACE=CGI/1.1";
+ envp[envn++] = build_env("SERVER_PROTOCOL=%s", hc->protocol);
+ (void) my_snprintf( buf, sizeof(buf), "%d", (int) hc->hs->port );
+ envp[envn++] = build_env( "SERVER_PORT=%s", buf );
+ envp[envn++] = build_env(
+ "REQUEST_METHOD=%s", httpd_method_str( hc->method ) );
+ if ( hc->pathinfo[0] != '\0' )
+ {
+ char* cp2;
+ size_t l;
+ envp[envn++] = build_env( "PATH_INFO=/%s", hc->pathinfo );
+ l = strlen( hc->hs->cwd ) + strlen( hc->pathinfo ) + 1;
+ cp2 = NEW( char, l );
+ if ( cp2 != (char*) 0 )
+ {
+ (void) my_snprintf( cp2, l, "%s%s", hc->hs->cwd, hc->pathinfo );
+ envp[envn++] = build_env( "PATH_TRANSLATED=%s", cp2 );
+ }
+ }
+ envp[envn++] = build_env(
+ "SCRIPT_NAME=/%s", strcmp( hc->origfilename, "." ) == 0 ?
+ "" : hc->origfilename );
+ if ( hc->query[0] != '\0')
+ envp[envn++] = build_env( "QUERY_STRING=%s", hc->query );
+ envp[envn++] = build_env(
+ "REMOTE_ADDR=%s", httpd_ntoa( &hc->client_addr ) );
+ if ( hc->referrer[0] != '\0' )
+ {
+ envp[envn++] = build_env( "HTTP_REFERER=%s", hc->referrer );
+ envp[envn++] = build_env( "HTTP_REFERRER=%s", hc->referrer );
+ }
+ if ( hc->useragent[0] != '\0' )
+ envp[envn++] = build_env( "HTTP_USER_AGENT=%s", hc->useragent );
+ if ( hc->accept[0] != '\0' )
+ envp[envn++] = build_env( "HTTP_ACCEPT=%s", hc->accept );
+ if ( hc->accepte[0] != '\0' )
+ envp[envn++] = build_env( "HTTP_ACCEPT_ENCODING=%s", hc->accepte );
+ if ( hc->acceptl[0] != '\0' )
+ envp[envn++] = build_env( "HTTP_ACCEPT_LANGUAGE=%s", hc->acceptl );
+ if ( hc->cookie[0] != '\0' )
+ envp[envn++] = build_env( "HTTP_COOKIE=%s", hc->cookie );
+ if ( hc->contenttype[0] != '\0' )
+ envp[envn++] = build_env( "CONTENT_TYPE=%s", hc->contenttype );
+ if ( hc->hdrhost[0] != '\0' )
+ envp[envn++] = build_env( "HTTP_HOST=%s", hc->hdrhost );
+ if ( hc->contentlength != -1 )
+ {
+ (void) my_snprintf(
+ buf, sizeof(buf), "%lu", (unsigned long) hc->contentlength );
+ envp[envn++] = build_env( "CONTENT_LENGTH=%s", buf );
+ }
+ if ( hc->remoteuser[0] != '\0' )
+ envp[envn++] = build_env( "REMOTE_USER=%s", hc->remoteuser );
+ if ( hc->authorization[0] != '\0' )
+ envp[envn++] = build_env( "AUTH_TYPE=%s", "Basic" );
+ /* We only support Basic auth at the moment. */
+ if ( getenv( "TZ" ) != (char*) 0 )
+ envp[envn++] = build_env( "TZ=%s", getenv( "TZ" ) );
+ envp[envn++] = build_env( "CGI_PATTERN=%s", hc->hs->cgi_pattern );
+
+ envp[envn] = (char*) 0;
+ return envp;
+ }
+
+
+/* Set up argument vector. Again, we don't have to worry about freeing stuff
+** since we're a sub-process. This gets done after make_envp() because we
+** scribble on hc->query.
+*/
+static char**
+make_argp( httpd_conn* hc )
+ {
+ char** argp;
+ int argn;
+ char* cp1;
+ char* cp2;
+
+ /* By allocating an arg slot for every character in the query, plus
+ ** one for the filename and one for the NULL, we are guaranteed to
+ ** have enough. We could actually use strlen/2.
+ */
+ argp = NEW( char*, strlen( hc->query ) + 2 );
+ if ( argp == (char**) 0 )
+ return (char**) 0;
+
+ argp[0] = strrchr( hc->expnfilename, '/' );
+ if ( argp[0] != (char*) 0 )
+ ++argp[0];
+ else
+ argp[0] = hc->expnfilename;
+
+ argn = 1;
+ /* According to the CGI spec at http://hoohoo.ncsa.uiuc.edu/cgi/cl.html,
+ ** "The server should search the query information for a non-encoded =
+ ** character to determine if the command line is to be used, if it finds
+ ** one, the command line is not to be used."
+ */
+ if ( strchr( hc->query, '=' ) == (char*) 0 )
+ {
+ for ( cp1 = cp2 = hc->query; *cp2 != '\0'; ++cp2 )
+ {
+ if ( *cp2 == '+' )
+ {
+ *cp2 = '\0';
+ strdecode( cp1, cp1 );
+ argp[argn++] = cp1;
+ cp1 = cp2 + 1;
+ }
+ }
+ if ( cp2 != cp1 )
+ {
+ strdecode( cp1, cp1 );
+ argp[argn++] = cp1;
+ }
+ }
+
+ argp[argn] = (char*) 0;
+ return argp;
+ }
+
+
+/* This routine is used only for POST requests. It reads the data
+** from the request and sends it to the child process. The only reason
+** we need to do it this way instead of just letting the child read
+** directly is that we have already read part of the data into our
+** buffer.
+*/
+static void
+cgi_interpose_input( httpd_conn* hc, int wfd )
+ {
+ size_t c;
+ ssize_t r;
+ char buf[1024];
+
+ c = hc->read_idx - hc->checked_idx;
+ if ( c > 0 )
+ {
+ if ( httpd_write_fully( wfd, &(hc->read_buf[hc->checked_idx]), c ) != c )
+ return;
+ }
+ while ( c < hc->contentlength )
+ {
+ r = read( hc->conn_fd, buf, MIN( sizeof(buf), hc->contentlength - c ) );
+ if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) )
+ {
+ sleep( 1 );
+ continue;
+ }
+ if ( r <= 0 )
+ return;
+ if ( httpd_write_fully( wfd, buf, r ) != r )
+ return;
+ c += r;
+ }
+ post_post_garbage_hack( hc );
+ }
+
+
+/* Special hack to deal with broken browsers that send a LF or CRLF
+** after POST data, causing TCP resets - we just read and discard up
+** to 2 bytes. Unfortunately this doesn't fix the problem for CGIs
+** which avoid the interposer process due to their POST data being
+** short. Creating an interposer process for all POST CGIs is
+** unacceptably expensive. The eventual fix will come when interposing
+** gets integrated into the main loop as a tasklet instead of a process.
+*/
+static void
+post_post_garbage_hack( httpd_conn* hc )
+ {
+ char buf[2];
+
+ /* If we are in a sub-process, turn on no-delay mode in case we
+ ** previously cleared it.
+ */
+ if ( sub_process )
+ httpd_set_ndelay( hc->conn_fd );
+ /* And read up to 2 bytes. */
+ (void) read( hc->conn_fd, buf, sizeof(buf) );
+ }
+
+
+/* This routine is used for parsed-header CGIs. The idea here is that the
+** CGI can return special headers such as "Status:" and "Location:" which
+** change the return status of the response. Since the return status has to
+** be the very first line written out, we have to accumulate all the headers
+** and check for the special ones before writing the status. Then we write
+** out the saved headers and proceed to echo the rest of the response.
+*/
+static void
+cgi_interpose_output( httpd_conn* hc, int rfd )
+ {
+ int r;
+ char buf[1024];
+ size_t headers_size, headers_len;
+ char* headers;
+ char* br;
+ int status;
+ char* title;
+ char* cp;
+
+ /* Make sure the connection is in blocking mode. It should already
+ ** be blocking, but we might as well be sure.
+ */
+ httpd_clear_ndelay( hc->conn_fd );
+
+ /* Slurp in all headers. */
+ headers_size = 0;
+ httpd_realloc_str( &headers, &headers_size, 500 );
+ headers_len = 0;
+ for (;;)
+ {
+ r = read( rfd, buf, sizeof(buf) );
+ if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) )
+ {
+ sleep( 1 );
+ continue;
+ }
+ if ( r <= 0 )
+ {
+ br = &(headers[headers_len]);
+ break;
+ }
+ httpd_realloc_str( &headers, &headers_size, headers_len + r );
+ (void) memmove( &(headers[headers_len]), buf, r );
+ headers_len += r;
+ headers[headers_len] = '\0';
+ if ( ( br = strstr( headers, "\015\012\015\012" ) ) != (char*) 0 ||
+ ( br = strstr( headers, "\012\012" ) ) != (char*) 0 )
+ break;
+ }
+
+ /* If there were no headers, bail. */
+ if ( headers[0] == '\0' )
+ return;
+
+ /* Figure out the status. Look for a Status: or Location: header;
+ ** else if there's an HTTP header line, get it from there; else
+ ** default to 200.
+ */
+ status = 200;
+ if ( strncmp( headers, "HTTP/", 5 ) == 0 )
+ {
+ cp = headers;
+ cp += strcspn( cp, " \t" );
+ status = atoi( cp );
+ }
+ if ( ( cp = strstr( headers, "Location:" ) ) != (char*) 0 &&
+ cp < br &&
+ ( cp == headers || *(cp-1) == '\012' ) )
+ status = 302;
+ if ( ( cp = strstr( headers, "Status:" ) ) != (char*) 0 &&
+ cp < br &&
+ ( cp == headers || *(cp-1) == '\012' ) )
+ {
+ cp += 7;
+ cp += strspn( cp, " \t" );
+ status = atoi( cp );
+ }
+
+ /* Write the status line. */
+ switch ( status )
+ {
+ case 200: title = ok200title; break;
+ case 302: title = err302title; break;
+ case 304: title = err304title; break;
+ case 400: title = httpd_err400title; break;
+#ifdef AUTH_FILE
+ case 401: title = err401title; break;
+#endif /* AUTH_FILE */
+ case 403: title = err403title; break;
+ case 404: title = err404title; break;
+ case 408: title = httpd_err408title; break;
+ case 451: title = err451title; break;
+ case 500: title = err500title; break;
+ case 501: title = err501title; break;
+ case 503: title = httpd_err503title; break;
+ default: title = "Something"; break;
+ }
+ (void) my_snprintf( buf, sizeof(buf), "HTTP/1.0 %d %s\015\012", status, title );
+ (void) httpd_write_fully( hc->conn_fd, buf, strlen( buf ) );
+
+ /* Write the saved headers. */
+ (void) httpd_write_fully( hc->conn_fd, headers, headers_len );
+
+ /* Echo the rest of the output. */
+ for (;;)
+ {
+ r = read( rfd, buf, sizeof(buf) );
+ if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) )
+ {
+ sleep( 1 );
+ continue;
+ }
+ if ( r <= 0 )
+ break;
+ if ( httpd_write_fully( hc->conn_fd, buf, r ) != r )
+ break;
+ }
+ shutdown( hc->conn_fd, SHUT_WR );
+ }
+
+
+/* CGI child process. */
+static void
+cgi_child( httpd_conn* hc )
+ {
+ int r;
+ char** argp;
+ char** envp;
+ char* binary;
+ char* directory;
+
+ /* Unset close-on-exec flag for this socket. This actually shouldn't
+ ** be necessary, according to POSIX a dup()'d file descriptor does
+ ** *not* inherit the close-on-exec flag, its flag is always clear.
+ ** However, Linux messes this up and does copy the flag to the
+ ** dup()'d descriptor, so we have to clear it. This could be
+ ** ifdeffed for Linux only.
+ */
+ (void) fcntl( hc->conn_fd, F_SETFD, 0 );
+
+ /* Close the syslog descriptor so that the CGI program can't
+ ** mess with it. All other open descriptors should be either
+ ** the listen socket(s), sockets from accept(), or the file-logging
+ ** fd, and all of those are set to close-on-exec, so we don't
+ ** have to close anything else.
+ */
+ closelog();
+
+ /* If the socket happens to be using one of the stdin/stdout/stderr
+ ** descriptors, move it to another descriptor so that the dup2 calls
+ ** below don't screw things up. We arbitrarily pick fd 3 - if there
+ ** was already something on it, we clobber it, but that doesn't matter
+ ** since at this point the only fd of interest is the connection.
+ ** All others will be closed on exec.
+ */
+ if ( hc->conn_fd == STDIN_FILENO || hc->conn_fd == STDOUT_FILENO || hc->conn_fd == STDERR_FILENO )
+ {
+ int newfd = dup2( hc->conn_fd, STDERR_FILENO + 1 );
+ if ( newfd >= 0 )
+ hc->conn_fd = newfd;
+ /* If the dup2 fails, shrug. We'll just take our chances.
+ ** Shouldn't happen though.
+ */
+ }
+
+ /* Make the environment vector. */
+ envp = make_envp( hc );
+
+ /* Make the argument vector. */
+ argp = make_argp( hc );
+
+ /* Set up stdin. For POSTs we may have to set up a pipe from an
+ ** interposer process, depending on if we've read some of the data
+ ** into our buffer.
+ */
+ if ( hc->method == METHOD_POST && hc->read_idx > hc->checked_idx )
+ {
+ int p[2];
+
+ if ( pipe( p ) < 0 )
+ {
+ syslog( LOG_ERR, "pipe - %m" );
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ httpd_write_response( hc );
+ exit( 1 );
+ }
+ r = fork( );
+ if ( r < 0 )
+ {
+ syslog( LOG_ERR, "fork - %m" );
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ httpd_write_response( hc );
+ exit( 1 );
+ }
+ if ( r == 0 )
+ {
+ /* Interposer process. */
+ sub_process = 1;
+ (void) close( p[0] );
+ cgi_interpose_input( hc, p[1] );
+ exit( 0 );
+ }
+ /* Need to schedule a kill for process r; but in the main process! */
+ (void) close( p[1] );
+ if ( p[0] != STDIN_FILENO )
+ {
+ (void) dup2( p[0], STDIN_FILENO );
+ (void) close( p[0] );
+ }
+ }
+ else
+ {
+ /* Otherwise, the request socket is stdin. */
+ if ( hc->conn_fd != STDIN_FILENO )
+ (void) dup2( hc->conn_fd, STDIN_FILENO );
+ }
+
+ /* Set up stdout/stderr. If we're doing CGI header parsing,
+ ** we need an output interposer too.
+ */
+ if ( strncmp( argp[0], "nph-", 4 ) != 0 && hc->mime_flag )
+ {
+ int p[2];
+
+ if ( pipe( p ) < 0 )
+ {
+ syslog( LOG_ERR, "pipe - %m" );
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ httpd_write_response( hc );
+ exit( 1 );
+ }
+ r = fork( );
+ if ( r < 0 )
+ {
+ syslog( LOG_ERR, "fork - %m" );
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ httpd_write_response( hc );
+ exit( 1 );
+ }
+ if ( r == 0 )
+ {
+ /* Interposer process. */
+ sub_process = 1;
+ (void) close( p[1] );
+ cgi_interpose_output( hc, p[0] );
+ exit( 0 );
+ }
+ /* Need to schedule a kill for process r; but in the main process! */
+ (void) close( p[0] );
+ if ( p[1] != STDOUT_FILENO )
+ (void) dup2( p[1], STDOUT_FILENO );
+ if ( p[1] != STDERR_FILENO )
+ (void) dup2( p[1], STDERR_FILENO );
+ if ( p[1] != STDOUT_FILENO && p[1] != STDERR_FILENO )
+ (void) close( p[1] );
+ }
+ else
+ {
+ /* Otherwise, the request socket is stdout/stderr. */
+ if ( hc->conn_fd != STDOUT_FILENO )
+ (void) dup2( hc->conn_fd, STDOUT_FILENO );
+ if ( hc->conn_fd != STDERR_FILENO )
+ (void) dup2( hc->conn_fd, STDERR_FILENO );
+ }
+
+ /* At this point we would like to set close-on-exec again for hc->conn_fd
+ ** (see previous comments on Linux's broken behavior re: close-on-exec
+ ** and dup.) Unfortunately there seems to be another Linux problem, or
+ ** perhaps a different aspect of the same problem - if we do this
+ ** close-on-exec in Linux, the socket stays open but stderr gets
+ ** closed - the last fd duped from the socket. What a mess. So we'll
+ ** just leave the socket as is, which under other OSs means an extra
+ ** file descriptor gets passed to the child process. Since the child
+ ** probably already has that file open via stdin stdout and/or stderr,
+ ** this is not a problem.
+ */
+ /* (void) fcntl( hc->conn_fd, F_SETFD, 1 ); */
+
+#ifdef CGI_NICE
+ /* Set priority. */
+ (void) nice( CGI_NICE );
+#endif /* CGI_NICE */
+
+ /* Split the program into directory and binary, so we can chdir()
+ ** to the program's own directory. This isn't in the CGI 1.1
+ ** spec, but it's what other HTTP servers do.
+ */
+ directory = strdup( hc->expnfilename );
+ if ( directory == (char*) 0 )
+ binary = hc->expnfilename; /* ignore errors */
+ else
+ {
+ binary = strrchr( directory, '/' );
+ if ( binary == (char*) 0 )
+ binary = hc->expnfilename;
+ else
+ {
+ *binary++ = '\0';
+ (void) chdir( directory ); /* ignore errors */
+ }
+ }
+
+ /* Default behavior for SIGPIPE. */
+#ifdef HAVE_SIGSET
+ (void) sigset( SIGPIPE, SIG_DFL );
+#else /* HAVE_SIGSET */
+ (void) signal( SIGPIPE, SIG_DFL );
+#endif /* HAVE_SIGSET */
+
+ /* Run the program. */
+ (void) execve( binary, argp, envp );
+
+ /* Something went wrong. */
+ syslog( LOG_ERR, "execve %.80s - %m", hc->expnfilename );
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ httpd_write_response( hc );
+ _exit( 1 );
+ }
+
+
+static int
+cgi( httpd_conn* hc )
+ {
+ int r;
+ ClientData client_data;
+
+ if ( hc->hs->cgi_limit != 0 && hc->hs->cgi_count >= hc->hs->cgi_limit )
+ {
+ httpd_send_err(
+ hc, 503, httpd_err503title, "", httpd_err503form,
+ hc->encodedurl );
+ return -1;
+ }
+ ++hc->hs->cgi_count;
+ httpd_clear_ndelay( hc->conn_fd );
+ r = fork( );
+ if ( r < 0 )
+ {
+ syslog( LOG_ERR, "fork - %m" );
+ httpd_send_err(
+ hc, 500, err500title, "", err500form, hc->encodedurl );
+ return -1;
+ }
+ if ( r == 0 )
+ {
+ /* Child process. */
+ sub_process = 1;
+ httpd_unlisten( hc->hs );
+ cgi_child( hc );
+ }
+
+ /* Parent process. */
+ syslog( LOG_DEBUG, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename );
+#ifdef CGI_TIMELIMIT
+ /* Schedule a kill for the child process, in case it runs too long */
+ client_data.i = r;
+ if ( tmr_create( (struct timeval*) 0, cgi_kill, client_data, CGI_TIMELIMIT * 1000L, 0 ) == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(cgi_kill child) failed" );
+ exit( 1 );
+ }
+#endif /* CGI_TIMELIMIT */
+ hc->status = 200;
+ hc->bytes_sent = CGI_BYTECOUNT;
+ hc->should_linger = 0;
+
+ return 0;
+ }
+
+
+static int
+really_start_request( httpd_conn* hc, struct timeval* nowP )
+ {
+ static char* indexname;
+ static size_t maxindexname = 0;
+ static const char* index_names[] = { INDEX_NAMES };
+ int i;
+#ifdef AUTH_FILE
+ static char* dirname;
+ static size_t maxdirname = 0;
+#endif /* AUTH_FILE */
+ size_t expnlen, indxlen;
+ char* cp;
+ char* pi;
+
+ expnlen = strlen( hc->expnfilename );
+
+ /* Stat the file. */
+ if ( stat( hc->expnfilename, &hc->sb ) < 0 )
+ {
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ return -1;
+ }
+
+ /* Is it world-readable or world-executable? We check explicitly instead
+ ** of just trying to open it, so that no one ever gets surprised by
+ ** a file that's not set world-readable and yet somehow is
+ ** readable by the HTTP server and therefore the *whole* world.
+ */
+ if ( ! ( hc->sb.st_mode & ( S_IROTH | S_IXOTH ) ) )
+ {
+ syslog(
+ LOG_INFO,
+ "%.80s URL \"%.80s\" resolves to a non world-readable file",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' resolves to a file that is not world-readable.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+
+ /* Is it a directory? */
+ if ( S_ISDIR(hc->sb.st_mode) )
+ {
+ /* If there's pathinfo, it's just a non-existent file. */
+ if ( hc->pathinfo[0] != '\0' )
+ {
+ httpd_send_err( hc, 404, err404title, "", err404form, hc->encodedurl );
+ return -1;
+ }
+
+ /* Special handling for directory URLs that don't end in a slash.
+ ** We send back an explicit redirect with the slash, because
+ ** otherwise many clients can't build relative URLs properly.
+ */
+ if ( strcmp( hc->origfilename, "" ) != 0 &&
+ strcmp( hc->origfilename, "." ) != 0 &&
+ hc->origfilename[strlen( hc->origfilename ) - 1] != '/' )
+ {
+ send_dirredirect( hc );
+ return -1;
+ }
+
+ /* Check for an index file. */
+ for ( i = 0; i < sizeof(index_names) / sizeof(char*); ++i )
+ {
+ httpd_realloc_str(
+ &indexname, &maxindexname,
+ expnlen + 1 + strlen( index_names[i] ) );
+ (void) strcpy( indexname, hc->expnfilename );
+ indxlen = strlen( indexname );
+ if ( indxlen == 0 || indexname[indxlen - 1] != '/' )
+ (void) strcat( indexname, "/" );
+ if ( strcmp( indexname, "./" ) == 0 )
+ indexname[0] = '\0';
+ (void) strcat( indexname, index_names[i] );
+ if ( stat( indexname, &hc->sb ) >= 0 )
+ goto got_one;
+ }
+
+ /* Nope, no index file, so it's an actual directory request. */
+#ifdef GENERATE_INDEXES
+ /* Directories must be readable for indexing. */
+ if ( ! ( hc->sb.st_mode & S_IROTH ) )
+ {
+ syslog(
+ LOG_INFO,
+ "%.80s URL \"%.80s\" tried to index a directory with indexing disabled",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' resolves to a directory that has indexing disabled.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+#ifdef AUTH_FILE
+ /* Check authorization for this directory. */
+ if ( auth_check( hc, hc->expnfilename ) == -1 )
+ return -1;
+#endif /* AUTH_FILE */
+ /* Referrer check. */
+ if ( ! check_referrer( hc ) )
+ return -1;
+ /* Ok, generate an index. */
+ return ls( hc );
+#else /* GENERATE_INDEXES */
+ syslog(
+ LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' is a directory, and directory indexing is disabled on this server.\n" ),
+ hc->encodedurl );
+ return -1;
+#endif /* GENERATE_INDEXES */
+
+ got_one: ;
+ /* Got an index file. Expand symlinks again. More pathinfo means
+ ** something went wrong.
+ */
+ cp = expand_symlinks( indexname, &pi, hc->hs->no_symlink_check, hc->tildemapped );
+ if ( cp == (char*) 0 || pi[0] != '\0' )
+ {
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ return -1;
+ }
+ expnlen = strlen( cp );
+ httpd_realloc_str( &hc->expnfilename, &hc->maxexpnfilename, expnlen );
+ (void) strcpy( hc->expnfilename, cp );
+
+ /* Now, is the index version world-readable or world-executable? */
+ if ( ! ( hc->sb.st_mode & ( S_IROTH | S_IXOTH ) ) )
+ {
+ syslog(
+ LOG_INFO,
+ "%.80s URL \"%.80s\" resolves to a non-world-readable index file",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' resolves to an index file that is not world-readable.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+ }
+
+#ifdef AUTH_FILE
+ /* Check authorization for this directory. */
+ httpd_realloc_str( &dirname, &maxdirname, expnlen );
+ (void) strcpy( dirname, hc->expnfilename );
+ cp = strrchr( dirname, '/' );
+ if ( cp == (char*) 0 )
+ (void) strcpy( dirname, "." );
+ else
+ *cp = '\0';
+ if ( auth_check( hc, dirname ) == -1 )
+ return -1;
+
+ /* Check if the filename is the AUTH_FILE itself - that's verboten. */
+ if ( expnlen == sizeof(AUTH_FILE) - 1 )
+ {
+ if ( strcmp( hc->expnfilename, AUTH_FILE ) == 0 )
+ {
+ syslog(
+ LOG_NOTICE,
+ "%.80s URL \"%.80s\" tried to retrieve an auth file",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' is an authorization file, retrieving it is not permitted.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+ }
+ else if ( expnlen >= sizeof(AUTH_FILE) &&
+ strcmp( &(hc->expnfilename[expnlen - sizeof(AUTH_FILE) + 1]), AUTH_FILE ) == 0 &&
+ hc->expnfilename[expnlen - sizeof(AUTH_FILE)] == '/' )
+ {
+ syslog(
+ LOG_NOTICE,
+ "%.80s URL \"%.80s\" tried to retrieve an auth file",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' is an authorization file, retrieving it is not permitted.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+#endif /* AUTH_FILE */
+
+ /* Referrer check. */
+ if ( ! check_referrer( hc ) )
+ return -1;
+
+ /* Is it world-executable and in the CGI area? */
+ if ( hc->hs->cgi_pattern != (char*) 0 &&
+ ( hc->sb.st_mode & S_IXOTH ) &&
+ match( hc->hs->cgi_pattern, hc->expnfilename ) )
+ return cgi( hc );
+
+ /* It's not CGI. If it's executable or there's pathinfo, someone's
+ ** trying to either serve or run a non-CGI file as CGI. Either case
+ ** is prohibited.
+ */
+ if ( hc->sb.st_mode & S_IXOTH )
+ {
+ syslog(
+ LOG_NOTICE, "%.80s URL \"%.80s\" is executable but isn't CGI",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' resolves to a file which is marked executable but is not a CGI file; retrieving it is forbidden.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+ if ( hc->pathinfo[0] != '\0' )
+ {
+ syslog(
+ LOG_INFO, "%.80s URL \"%.80s\" has pathinfo but isn't CGI",
+ httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "The requested URL '%.80s' resolves to a file plus CGI-style pathinfo, but the file is not a valid CGI file.\n" ),
+ hc->encodedurl );
+ return -1;
+ }
+
+ if ( hc->method != METHOD_GET && hc->method != METHOD_HEAD )
+ {
+ httpd_send_err(
+ hc, 501, err501title, "", err501form, httpd_method_str( hc->method ) );
+ return -1;
+ }
+
+ /* Fill in last_byte_index, if necessary. */
+ if ( hc->got_range &&
+ ( hc->last_byte_index == -1 || hc->last_byte_index >= hc->sb.st_size ) )
+ hc->last_byte_index = hc->sb.st_size - 1;
+
+ figure_mime( hc );
+
+ if ( hc->method == METHOD_HEAD )
+ {
+ send_mime(
+ hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size,
+ hc->sb.st_mtime );
+ }
+ else if ( hc->if_modified_since != (time_t) -1 &&
+ hc->if_modified_since >= hc->sb.st_mtime )
+ {
+ send_mime(
+ hc, 304, err304title, hc->encodings, "", hc->type, (off_t) -1,
+ hc->sb.st_mtime );
+ }
+ else
+ {
+ hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP );
+ if ( hc->file_address == (char*) 0 )
+ {
+ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
+ return -1;
+ }
+ send_mime(
+ hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size,
+ hc->sb.st_mtime );
+ }
+
+ return 0;
+ }
+
+
+int
+httpd_start_request( httpd_conn* hc, struct timeval* nowP )
+ {
+ int r;
+
+ /* Really start the request. */
+ r = really_start_request( hc, nowP );
+
+ /* And return the status. */
+ return r;
+ }
+
+
+static void
+make_log_entry( httpd_conn* hc, struct timeval* nowP )
+ {
+ char* ru;
+ char url[305];
+ char bytes[40];
+
+ if ( hc->hs->no_log )
+ return;
+
+ /* This is straight CERN Combined Log Format - the only tweak
+ ** being that if we're using syslog() we leave out the date, because
+ ** syslogd puts it in. The included syslogtocern script turns the
+ ** results into true CERN format.
+ */
+
+ /* Format remote user. */
+ if ( hc->remoteuser[0] != '\0' )
+ ru = hc->remoteuser;
+ else
+ ru = "-";
+ /* If we're vhosting, prepend the hostname to the url. This is
+ ** a little weird, perhaps writing separate log files for
+ ** each vhost would make more sense.
+ */
+ if ( hc->hs->vhost && ! hc->tildemapped )
+ (void) my_snprintf( url, sizeof(url),
+ "/%.100s%.200s",
+ hc->hostname == (char*) 0 ? hc->hs->server_hostname : hc->hostname,
+ hc->encodedurl );
+ else
+ (void) my_snprintf( url, sizeof(url),
+ "%.200s", hc->encodedurl );
+ /* Format the bytes. */
+ if ( hc->bytes_sent >= 0 )
+ (void) my_snprintf(
+ bytes, sizeof(bytes), "%lld", (long long) hc->bytes_sent );
+ else
+ (void) strcpy( bytes, "-" );
+
+ /* Logfile or syslog? */
+ if ( hc->hs->logfp != (FILE*) 0 )
+ {
+ time_t now;
+ struct tm* t;
+ const char* cernfmt_nozone = "%d/%b/%Y:%H:%M:%S";
+ char date_nozone[100];
+ int zone;
+ char sign;
+ char date[100];
+
+ /* Get the current time, if necessary. */
+ if ( nowP != (struct timeval*) 0 )
+ now = nowP->tv_sec;
+ else
+ now = time( (time_t*) 0 );
+ /* Format the time, forcing a numeric timezone (some log analyzers
+ ** are stoooopid about this).
+ */
+ t = localtime( &now );
+ (void) strftime( date_nozone, sizeof(date_nozone), cernfmt_nozone, t );
+#ifdef HAVE_TM_GMTOFF
+ zone = t->tm_gmtoff / 60L;
+#else
+ zone = -timezone / 60L;
+ /* Probably have to add something about daylight time here. */
+#endif
+ if ( zone >= 0 )
+ sign = '+';
+ else
+ {
+ sign = '-';
+ zone = -zone;
+ }
+ zone = ( zone / 60 ) * 100 + zone % 60;
+ (void) my_snprintf( date, sizeof(date),
+ "%s %c%04d", date_nozone, sign, zone );
+ /* And write the log entry. */
+ (void) fprintf( hc->hs->logfp,
+ "%.80s - %.80s [%s] \"%.80s %.300s %.80s\" %d %s \"%.200s\" \"%.200s\"\n",
+ httpd_ntoa( &hc->client_addr ), ru, date,
+ httpd_method_str( hc->method ), url, hc->protocol,
+ hc->status, bytes, hc->referrer, hc->useragent );
+#ifdef FLUSH_LOG_EVERY_TIME
+ (void) fflush( hc->hs->logfp );
+#endif
+ }
+ else
+ syslog( LOG_INFO,
+ "%.80s - %.80s \"%.80s %.200s %.80s\" %d %s \"%.200s\" \"%.200s\"",
+ httpd_ntoa( &hc->client_addr ), ru,
+ httpd_method_str( hc->method ), url, hc->protocol,
+ hc->status, bytes, hc->referrer, hc->useragent );
+ }
+
+
+/* Returns 1 if ok to serve the url, 0 if not. */
+static int
+check_referrer( httpd_conn* hc )
+ {
+ int r;
+ char* cp;
+
+ /* Are we doing referrer checking at all? */
+ if ( hc->hs->url_pattern == (char*) 0 )
+ return 1;
+
+ r = really_check_referrer( hc );
+
+ if ( ! r )
+ {
+ if ( hc->hs->vhost && hc->hostname != (char*) 0 )
+ cp = hc->hostname;
+ else
+ cp = hc->hs->server_hostname;
+ if ( cp == (char*) 0 )
+ cp = "";
+ syslog(
+ LOG_INFO, "%.80s non-local referrer \"%.80s%.80s\" \"%.80s\"",
+ httpd_ntoa( &hc->client_addr ), cp, hc->encodedurl, hc->referrer );
+ httpd_send_err(
+ hc, 403, err403title, "",
+ ERROR_FORM( err403form, "You must supply a local referrer to get URL '%.80s' from this server.\n" ),
+ hc->encodedurl );
+ }
+ return r;
+ }
+
+
+/* Returns 1 if ok to serve the url, 0 if not. */
+static int
+really_check_referrer( httpd_conn* hc )
+ {
+ httpd_server* hs;
+ char* cp1;
+ char* cp2;
+ char* cp3;
+ static char* refhost = (char*) 0;
+ static size_t refhost_size = 0;
+ char *lp;
+
+ hs = hc->hs;
+
+ /* Check for an empty referrer. */
+ if ( hc->referrer == (char*) 0 || hc->referrer[0] == '\0' ||
+ ( cp1 = strstr( hc->referrer, "//" ) ) == (char*) 0 )
+ {
+ /* Disallow if we require a referrer and the url matches. */
+ if ( hs->no_empty_referrers && match( hs->url_pattern, hc->origfilename ) )
+ return 0;
+ /* Otherwise ok. */
+ return 1;
+ }
+
+ /* Extract referrer host. */
+ cp1 += 2;
+ for ( cp2 = cp1; *cp2 != '/' && *cp2 != ':' && *cp2 != '\0'; ++cp2 )
+ continue;
+ httpd_realloc_str( &refhost, &refhost_size, cp2 - cp1 );
+ for ( cp3 = refhost; cp1 < cp2; ++cp1, ++cp3 )
+ if ( isupper(*cp1) )
+ *cp3 = tolower(*cp1);
+ else
+ *cp3 = *cp1;
+ *cp3 = '\0';
+
+ /* Local pattern? */
+ if ( hs->local_pattern != (char*) 0 )
+ lp = hs->local_pattern;
+ else
+ {
+ /* No local pattern. What's our hostname? */
+ if ( ! hs->vhost )
+ {
+ /* Not vhosting, use the server name. */
+ lp = hs->server_hostname;
+ if ( lp == (char*) 0 )
+ /* Couldn't figure out local hostname - give up. */
+ return 1;
+ }
+ else
+ {
+ /* We are vhosting, use the hostname on this connection. */
+ lp = hc->hostname;
+ if ( lp == (char*) 0 )
+ /* Oops, no hostname. Maybe it's an old browser that
+ ** doesn't send a Host: header. We could figure out
+ ** the default hostname for this IP address, but it's
+ ** not worth it for the few requests like this.
+ */
+ return 1;
+ }
+ }
+
+ /* If the referrer host doesn't match the local host pattern, and
+ ** the filename does match the url pattern, it's an illegal reference.
+ */
+ if ( ! match( lp, refhost ) && match( hs->url_pattern, hc->origfilename ) )
+ return 0;
+ /* Otherwise ok. */
+ return 1;
+ }
+
+
+char*
+httpd_ntoa( httpd_sockaddr* saP )
+ {
+#ifdef USE_IPV6
+ static char str[200];
+
+ if ( getnameinfo( &saP->sa, sockaddr_len( saP ), str, sizeof(str), 0, 0, NI_NUMERICHOST ) != 0 )
+ {
+ str[0] = '?';
+ str[1] = '\0';
+ }
+ else if ( IN6_IS_ADDR_V4MAPPED( &saP->sa_in6.sin6_addr ) && strncmp( str, "::ffff:", 7 ) == 0 )
+ /* Elide IPv6ish prefix for IPv4 addresses. */
+ (void) ol_strcpy( str, &str[7] );
+
+ return str;
+
+#else /* USE_IPV6 */
+
+ return inet_ntoa( saP->sa_in.sin_addr );
+
+#endif /* USE_IPV6 */
+ }
+
+
+static int
+sockaddr_check( httpd_sockaddr* saP )
+ {
+ switch ( saP->sa.sa_family )
+ {
+ case AF_INET: return 1;
+#ifdef USE_IPV6
+ case AF_INET6: return 1;
+#endif /* USE_IPV6 */
+ default:
+ return 0;
+ }
+ }
+
+
+static size_t
+sockaddr_len( httpd_sockaddr* saP )
+ {
+ switch ( saP->sa.sa_family )
+ {
+ case AF_INET: return sizeof(struct sockaddr_in);
+#ifdef USE_IPV6
+ case AF_INET6: return sizeof(struct sockaddr_in6);
+#endif /* USE_IPV6 */
+ default:
+ return 0; /* shouldn't happen */
+ }
+ }
+
+
+/* Some systems don't have snprintf(), so we make our own that uses
+** either vsnprintf() or vsprintf(). If your system doesn't have
+** vsnprintf(), it is probably vulnerable to buffer overruns.
+** Upgrade!
+*/
+static int
+my_snprintf( char* str, size_t size, const char* format, ... )
+ {
+ va_list ap;
+ int r;
+
+ va_start( ap, format );
+#ifdef HAVE_VSNPRINTF
+ r = vsnprintf( str, size, format, ap );
+#else /* HAVE_VSNPRINTF */
+ r = vsprintf( str, format, ap );
+#endif /* HAVE_VSNPRINTF */
+ va_end( ap );
+ return r;
+ }
+
+
+#ifndef HAVE_ATOLL
+static long long
+atoll( const char* str )
+ {
+ long long value;
+ long long sign;
+
+ while ( isspace( *str ) )
+ ++str;
+ switch ( *str )
+ {
+ case '-': sign = -1; ++str; break;
+ case '+': sign = 1; ++str; break;
+ default: sign = 1; break;
+ }
+ value = 0;
+ while ( isdigit( *str ) )
+ {
+ value = value * 10 + ( *str - '0' );
+ ++str;
+ }
+ return sign * value;
+ }
+#endif /* HAVE_ATOLL */
+
+
+/* Read the requested buffer completely, accounting for interruptions. */
+int
+httpd_read_fully( int fd, void* buf, size_t nbytes )
+ {
+ int nread;
+
+ nread = 0;
+ while ( nread < nbytes )
+ {
+ int r;
+
+ r = read( fd, (char*) buf + nread, nbytes - nread );
+ if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) )
+ {
+ sleep( 1 );
+ continue;
+ }
+ if ( r < 0 )
+ return r;
+ if ( r == 0 )
+ break;
+ nread += r;
+ }
+
+ return nread;
+ }
+
+
+/* Write the requested buffer completely, accounting for interruptions. */
+int
+httpd_write_fully( int fd, const char* buf, size_t nbytes )
+ {
+ int nwritten;
+
+ nwritten = 0;
+ while ( nwritten < nbytes )
+ {
+ int r;
+
+ r = write( fd, buf + nwritten, nbytes - nwritten );
+ if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) )
+ {
+ sleep( 1 );
+ continue;
+ }
+ if ( r < 0 )
+ return r;
+ if ( r == 0 )
+ break;
+ nwritten += r;
+ }
+
+ return nwritten;
+ }
+
+
+/* Generate debugging statistics syslog message. */
+void
+httpd_logstats( long secs )
+ {
+ if ( str_alloc_count > 0 )
+ syslog( LOG_NOTICE,
+ " libhttpd - %d strings allocated, %lu bytes (%g bytes/str)",
+ str_alloc_count, (unsigned long) str_alloc_size,
+ (float) str_alloc_size / str_alloc_count );
+ }
--- /dev/null
+/* libhttpd.h - defines for libhttpd
+**
+** Copyright © 1995,1998,1999,2000,2001 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#ifndef _LIBHTTPD_H_
+#define _LIBHTTPD_H_
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED)
+#define USE_IPV6
+#endif
+
+
+/* A few convenient defines. */
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#define NEW(t,n) ((t*) malloc( sizeof(t) * (n) ))
+#define RENEW(o,t,n) ((t*) realloc( (void*) o, sizeof(t) * (n) ))
+
+/* Do overlapping strcpy safely, by using memmove. */
+#define ol_strcpy(dst,src) memmove(dst,src,strlen(src)+1)
+
+
+/* The httpd structs. */
+
+/* A multi-family sockaddr. */
+typedef union {
+ struct sockaddr sa;
+ struct sockaddr_in sa_in;
+#ifdef USE_IPV6
+ struct sockaddr_in6 sa_in6;
+ struct sockaddr_storage sa_stor;
+#endif /* USE_IPV6 */
+ } httpd_sockaddr;
+
+/* A server. */
+typedef struct {
+ char* binding_hostname;
+ char* server_hostname;
+ unsigned short port;
+ char* cgi_pattern;
+ int cgi_limit, cgi_count;
+ char* charset;
+ char* p3p;
+ int max_age;
+ char* cwd;
+ int listen4_fd, listen6_fd;
+ int no_log;
+ FILE* logfp;
+ int no_symlink_check;
+ int vhost;
+ int global_passwd;
+ char* url_pattern;
+ char* local_pattern;
+ int no_empty_referrers;
+ } httpd_server;
+
+/* A connection. */
+typedef struct {
+ int initialized;
+ httpd_server* hs;
+ httpd_sockaddr client_addr;
+ char* read_buf;
+ size_t read_size, read_idx, checked_idx;
+ int checked_state;
+ int method;
+ int status;
+ off_t bytes_to_send;
+ off_t bytes_sent;
+ char* encodedurl;
+ char* decodedurl;
+ char* protocol;
+ char* origfilename;
+ char* expnfilename;
+ char* encodings;
+ char* pathinfo;
+ char* query;
+ char* referrer;
+ char* useragent;
+ char* accept;
+ char* accepte;
+ char* acceptl;
+ char* cookie;
+ char* contenttype;
+ char* reqhost;
+ char* hdrhost;
+ char* hostdir;
+ char* authorization;
+ char* remoteuser;
+ char* response;
+ size_t maxdecodedurl, maxorigfilename, maxexpnfilename, maxencodings,
+ maxpathinfo, maxquery, maxaccept, maxaccepte, maxreqhost, maxhostdir,
+ maxremoteuser, maxresponse;
+#ifdef TILDE_MAP_2
+ char* altdir;
+ size_t maxaltdir;
+#endif /* TILDE_MAP_2 */
+ size_t responselen;
+ time_t if_modified_since, range_if;
+ size_t contentlength;
+ char* type; /* not malloc()ed */
+ char* hostname; /* not malloc()ed */
+ int mime_flag;
+ int one_one; /* HTTP/1.1 or better */
+ int got_range;
+ int tildemapped; /* this connection got tilde-mapped */
+ off_t first_byte_index, last_byte_index;
+ int keep_alive;
+ int should_linger;
+ struct stat sb;
+ int conn_fd;
+ char* file_address;
+ } httpd_conn;
+
+/* Methods. */
+#define METHOD_UNKNOWN 0
+#define METHOD_GET 1
+#define METHOD_HEAD 2
+#define METHOD_POST 3
+#define METHOD_PUT 4
+#define METHOD_DELETE 5
+#define METHOD_TRACE 6
+
+/* States for checked_state. */
+#define CHST_FIRSTWORD 0
+#define CHST_FIRSTWS 1
+#define CHST_SECONDWORD 2
+#define CHST_SECONDWS 3
+#define CHST_THIRDWORD 4
+#define CHST_THIRDWS 5
+#define CHST_LINE 6
+#define CHST_LF 7
+#define CHST_CR 8
+#define CHST_CRLF 9
+#define CHST_CRLFCR 10
+#define CHST_BOGUS 11
+
+
+/* Initializes. Does the socket(), bind(), and listen(). Returns an
+** httpd_server* which includes a socket fd that you can select() on.
+** Return (httpd_server*) 0 on error.
+*/
+httpd_server* httpd_initialize(
+ char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P,
+ unsigned short port, char* cgi_pattern, int cgi_limit, char* charset,
+ char* p3p, int max_age, char* cwd, int no_log, FILE* logfp,
+ int no_symlink_check, int vhost, int global_passwd, char* url_pattern,
+ char* local_pattern, int no_empty_referrers );
+
+/* Change the log file. */
+void httpd_set_logfp( httpd_server* hs, FILE* logfp );
+
+/* Call to unlisten/close socket(s) listening for new connections. */
+void httpd_unlisten( httpd_server* hs );
+
+/* Call to shut down. */
+void httpd_terminate( httpd_server* hs );
+
+
+/* When a listen fd is ready to read, call this. It does the accept() and
+** returns an httpd_conn* which includes the fd to read the request from and
+** write the response to. Returns an indication of whether the accept()
+** failed, succeeded, or if there were no more connections to accept.
+**
+** In order to minimize malloc()s, the caller passes in the httpd_conn.
+** The caller is also responsible for setting initialized to zero before the
+** first call using each different httpd_conn.
+*/
+int httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc );
+#define GC_FAIL 0
+#define GC_OK 1
+#define GC_NO_MORE 2
+
+/* Checks whether the data in hc->read_buf constitutes a complete request
+** yet. The caller reads data into hc->read_buf[hc->read_idx] and advances
+** hc->read_idx. This routine checks what has been read so far, using
+** hc->checked_idx and hc->checked_state to keep track, and returns an
+** indication of whether there is no complete request yet, there is a
+** complete request, or there won't be a valid request due to a syntax error.
+*/
+int httpd_got_request( httpd_conn* hc );
+#define GR_NO_REQUEST 0
+#define GR_GOT_REQUEST 1
+#define GR_BAD_REQUEST 2
+
+/* Parses the request in hc->read_buf. Fills in lots of fields in hc,
+** like the URL and the various headers.
+**
+** Returns -1 on error.
+*/
+int httpd_parse_request( httpd_conn* hc );
+
+/* Starts sending data back to the client. In some cases (directories,
+** CGI programs), finishes sending by itself - in those cases, hc->file_fd
+** is <0. If there is more data to be sent, then hc->file_fd is a file
+** descriptor for the file to send. If you don't have a current timeval
+** handy just pass in 0.
+**
+** Returns -1 on error.
+*/
+int httpd_start_request( httpd_conn* hc, struct timeval* nowP );
+
+/* Actually sends any buffered response text. */
+void httpd_write_response( httpd_conn* hc );
+
+/* Call this to close down a connection and free the data. A fine point,
+** if you fork() with a connection open you should still call this in the
+** parent process - the connection will stay open in the child.
+** If you don't have a current timeval handy just pass in 0.
+*/
+void httpd_close_conn( httpd_conn* hc, struct timeval* nowP );
+
+/* Call this to de-initialize a connection struct and *really* free the
+** mallocced strings.
+*/
+void httpd_destroy_conn( httpd_conn* hc );
+
+
+/* Send an error message back to the client. */
+void httpd_send_err(
+ httpd_conn* hc, int status, char* title, char* extraheads, char* form,
+ char* arg );
+
+/* Some error messages. */
+extern char* httpd_err400title;
+extern char* httpd_err400form;
+extern char* httpd_err408title;
+extern char* httpd_err408form;
+extern char* httpd_err503title;
+extern char* httpd_err503form;
+
+/* Generate a string representation of a method number. */
+char* httpd_method_str( int method );
+
+/* Reallocate a string. */
+void httpd_realloc_str( char** strP, size_t* maxsizeP, size_t size );
+
+/* Format a network socket to a string representation. */
+char* httpd_ntoa( httpd_sockaddr* saP );
+
+/* Set NDELAY mode on a socket. */
+void httpd_set_ndelay( int fd );
+
+/* Clear NDELAY mode on a socket. */
+void httpd_clear_ndelay( int fd );
+
+/* Read the requested buffer completely, accounting for interruptions. */
+int httpd_read_fully( int fd, void* buf, size_t nbytes );
+
+/* Write the requested buffer completely, accounting for interruptions. */
+int httpd_write_fully( int fd, const char* buf, size_t nbytes );
+
+/* Generate debugging statistics syslog message. */
+void httpd_logstats( long secs );
+
+#endif /* _LIBHTTPD_H_ */
--- /dev/null
+/* match.c - simple shell-style filename matcher
+**
+** Only does ? * and **, and multiple patterns separated by |. Returns 1 or 0.
+**
+** Copyright © 1995,2000 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+
+#include <string.h>
+
+#include "match.h"
+
+static int match_one( const char* pattern, int patternlen, const char* string );
+
+int
+match( const char* pattern, const char* string )
+ {
+ const char* or;
+
+ for (;;)
+ {
+ or = strchr( pattern, '|' );
+ if ( or == (char*) 0 )
+ return match_one( pattern, strlen( pattern ), string );
+ if ( match_one( pattern, or - pattern, string ) )
+ return 1;
+ pattern = or + 1;
+ }
+ }
+
+
+static int
+match_one( const char* pattern, int patternlen, const char* string )
+ {
+ const char* p;
+
+ for ( p = pattern; p - pattern < patternlen; ++p, ++string )
+ {
+ if ( *p == '?' && *string != '\0' )
+ continue;
+ if ( *p == '*' )
+ {
+ int i, pl;
+ ++p;
+ if ( *p == '*' )
+ {
+ /* Double-wildcard matches anything. */
+ ++p;
+ i = strlen( string );
+ }
+ else
+ /* Single-wildcard matches anything but slash. */
+ i = strcspn( string, "/" );
+ pl = patternlen - ( p - pattern );
+ for ( ; i >= 0; --i )
+ if ( match_one( p, pl, &(string[i]) ) )
+ return 1;
+ return 0;
+ }
+ if ( *p != *string )
+ return 0;
+ }
+ if ( *string == '\0' )
+ return 1;
+ return 0;
+ }
--- /dev/null
+/* match.h - simple shell-style filename patcher
+**
+** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#ifndef _MATCH_H_
+#define _MATCH_H_
+
+/* Simple shell-style filename pattern matcher. Only does ? * and **, and
+** multiple patterns separated by |. Returns 1 or 0.
+*/
+int match( const char* pattern, const char* string );
+
+#endif /* _MATCH_H_ */
--- /dev/null
+{ "Z", 0, "compress", 0 },
+{ "gz", 0, "gzip", 0 },
+{ "uu", 0, "x-uuencode", 0 },
--- /dev/null
+# mime_encodings.txt
+#
+# A list of file extensions followed by the corresponding MIME encoding.
+# Extensions not found in the table proceed to the mime_types table.
+
+Z compress
+gz gzip
+uu x-uuencode
--- /dev/null
+{ "a", 0, "application/octet-stream", 0 },
+{ "aab", 0, "application/x-authorware-bin", 0 },
+{ "aam", 0, "application/x-authorware-map", 0 },
+{ "aas", 0, "application/x-authorware-seg", 0 },
+{ "ai", 0, "application/postscript", 0 },
+{ "aif", 0, "audio/x-aiff", 0 },
+{ "aifc", 0, "audio/x-aiff", 0 },
+{ "aiff", 0, "audio/x-aiff", 0 },
+{ "asc", 0, "text/plain; charset=%s", 0 },
+{ "asf", 0, "video/x-ms-asf", 0 },
+{ "asx", 0, "video/x-ms-asf", 0 },
+{ "au", 0, "audio/basic", 0 },
+{ "avi", 0, "video/x-msvideo", 0 },
+{ "bcpio", 0, "application/x-bcpio", 0 },
+{ "bin", 0, "application/octet-stream", 0 },
+{ "bmp", 0, "image/bmp", 0 },
+{ "cdf", 0, "application/x-netcdf", 0 },
+{ "class", 0, "application/x-java-vm", 0 },
+{ "cpio", 0, "application/x-cpio", 0 },
+{ "cpt", 0, "application/mac-compactpro", 0 },
+{ "crl", 0, "application/x-pkcs7-crl", 0 },
+{ "crt", 0, "application/x-x509-ca-cert", 0 },
+{ "csh", 0, "application/x-csh", 0 },
+{ "css", 0, "text/css; charset=%s", 0 },
+{ "dcr", 0, "application/x-director", 0 },
+{ "dir", 0, "application/x-director", 0 },
+{ "djv", 0, "image/vnd.djvu", 0 },
+{ "djvu", 0, "image/vnd.djvu", 0 },
+{ "dll", 0, "application/octet-stream", 0 },
+{ "dms", 0, "application/octet-stream", 0 },
+{ "doc", 0, "application/msword", 0 },
+{ "dtd", 0, "text/xml; charset=%s", 0 },
+{ "dump", 0, "application/octet-stream", 0 },
+{ "dvi", 0, "application/x-dvi", 0 },
+{ "dxr", 0, "application/x-director", 0 },
+{ "eps", 0, "application/postscript", 0 },
+{ "etx", 0, "text/x-setext", 0 },
+{ "exe", 0, "application/octet-stream", 0 },
+{ "ez", 0, "application/andrew-inset", 0 },
+{ "fgd", 0, "application/x-director", 0 },
+{ "fh", 0, "image/x-freehand", 0 },
+{ "fh4", 0, "image/x-freehand", 0 },
+{ "fh5", 0, "image/x-freehand", 0 },
+{ "fh7", 0, "image/x-freehand", 0 },
+{ "fhc", 0, "image/x-freehand", 0 },
+{ "gif", 0, "image/gif", 0 },
+{ "gtar", 0, "application/x-gtar", 0 },
+{ "hdf", 0, "application/x-hdf", 0 },
+{ "hqx", 0, "application/mac-binhex40", 0 },
+{ "htm", 0, "text/html; charset=%s", 0 },
+{ "html", 0, "text/html; charset=%s", 0 },
+{ "ice", 0, "x-conference/x-cooltalk", 0 },
+{ "ief", 0, "image/ief", 0 },
+{ "iges", 0, "model/iges", 0 },
+{ "igs", 0, "model/iges", 0 },
+{ "iv", 0, "application/x-inventor", 0 },
+{ "jar", 0, "application/x-java-archive", 0 },
+{ "jfif", 0, "image/jpeg", 0 },
+{ "jpe", 0, "image/jpeg", 0 },
+{ "jpeg", 0, "image/jpeg", 0 },
+{ "jpg", 0, "image/jpeg", 0 },
+{ "js", 0, "application/x-javascript", 0 },
+{ "kar", 0, "audio/midi", 0 },
+{ "kml", 0, "application/vnd.google-earth.kml+xml", 0 },
+{ "kmz", 0, "application/vnd.google-earth.kmz", 0 },
+{ "latex", 0, "application/x-latex", 0 },
+{ "lha", 0, "application/octet-stream", 0 },
+{ "loc", 0, "application/xml-loc", 0 },
+{ "lzh", 0, "application/octet-stream", 0 },
+{ "m3u", 0, "audio/x-mpegurl", 0 },
+{ "man", 0, "application/x-troff-man", 0 },
+{ "mathml", 0, "application/mathml+xml", 0 },
+{ "me", 0, "application/x-troff-me", 0 },
+{ "mesh", 0, "model/mesh", 0 },
+{ "mid", 0, "audio/midi", 0 },
+{ "midi", 0, "audio/midi", 0 },
+{ "mif", 0, "application/vnd.mif", 0 },
+{ "mime", 0, "message/rfc822", 0 },
+{ "mml", 0, "application/mathml+xml", 0 },
+{ "mov", 0, "video/quicktime", 0 },
+{ "movie", 0, "video/x-sgi-movie", 0 },
+{ "mp2", 0, "audio/mpeg", 0 },
+{ "mp3", 0, "audio/mpeg", 0 },
+{ "mp4", 0, "video/mp4", 0 },
+{ "mpe", 0, "video/mpeg", 0 },
+{ "mpeg", 0, "video/mpeg", 0 },
+{ "mpg", 0, "video/mpeg", 0 },
+{ "mpga", 0, "audio/mpeg", 0 },
+{ "ms", 0, "application/x-troff-ms", 0 },
+{ "msh", 0, "model/mesh", 0 },
+{ "mv", 0, "video/x-sgi-movie", 0 },
+{ "mxu", 0, "video/vnd.mpegurl", 0 },
+{ "nc", 0, "application/x-netcdf", 0 },
+{ "o", 0, "application/octet-stream", 0 },
+{ "oda", 0, "application/oda", 0 },
+{ "ogg", 0, "application/ogg", 0 },
+{ "pac", 0, "application/x-ns-proxy-autoconfig", 0 },
+{ "pbm", 0, "image/x-portable-bitmap", 0 },
+{ "pdb", 0, "chemical/x-pdb", 0 },
+{ "pdf", 0, "application/pdf", 0 },
+{ "pgm", 0, "image/x-portable-graymap", 0 },
+{ "pgn", 0, "application/x-chess-pgn", 0 },
+{ "png", 0, "image/png", 0 },
+{ "pnm", 0, "image/x-portable-anymap", 0 },
+{ "ppm", 0, "image/x-portable-pixmap", 0 },
+{ "ppt", 0, "application/vnd.ms-powerpoint", 0 },
+{ "ps", 0, "application/postscript", 0 },
+{ "qt", 0, "video/quicktime", 0 },
+{ "ra", 0, "audio/x-realaudio", 0 },
+{ "ram", 0, "audio/x-pn-realaudio", 0 },
+{ "ras", 0, "image/x-cmu-raster", 0 },
+{ "rdf", 0, "application/rdf+xml", 0 },
+{ "rgb", 0, "image/x-rgb", 0 },
+{ "rm", 0, "audio/x-pn-realaudio", 0 },
+{ "roff", 0, "application/x-troff", 0 },
+{ "rpm", 0, "audio/x-pn-realaudio-plugin", 0 },
+{ "rss", 0, "application/rss+xml", 0 },
+{ "rtf", 0, "text/rtf; charset=%s", 0 },
+{ "rtx", 0, "text/richtext; charset=%s", 0 },
+{ "sgm", 0, "text/sgml; charset=%s", 0 },
+{ "sgml", 0, "text/sgml; charset=%s", 0 },
+{ "sh", 0, "application/x-sh", 0 },
+{ "shar", 0, "application/x-shar", 0 },
+{ "silo", 0, "model/mesh", 0 },
+{ "sit", 0, "application/x-stuffit", 0 },
+{ "skd", 0, "application/x-koan", 0 },
+{ "skm", 0, "application/x-koan", 0 },
+{ "skp", 0, "application/x-koan", 0 },
+{ "skt", 0, "application/x-koan", 0 },
+{ "smi", 0, "application/smil", 0 },
+{ "smil", 0, "application/smil", 0 },
+{ "snd", 0, "audio/basic", 0 },
+{ "so", 0, "application/octet-stream", 0 },
+{ "spl", 0, "application/x-futuresplash", 0 },
+{ "src", 0, "application/x-wais-source", 0 },
+{ "stc", 0, "application/vnd.sun.xml.calc.template", 0 },
+{ "std", 0, "application/vnd.sun.xml.draw.template", 0 },
+{ "sti", 0, "application/vnd.sun.xml.impress.template", 0 },
+{ "stw", 0, "application/vnd.sun.xml.writer.template", 0 },
+{ "sv4cpio", 0, "application/x-sv4cpio", 0 },
+{ "sv4crc", 0, "application/x-sv4crc", 0 },
+{ "svg", 0, "image/svg+xml", 0 },
+{ "svgz", 0, "image/svg+xml", 0 },
+{ "swf", 0, "application/x-shockwave-flash", 0 },
+{ "sxc", 0, "application/vnd.sun.xml.calc", 0 },
+{ "sxd", 0, "application/vnd.sun.xml.draw", 0 },
+{ "sxg", 0, "application/vnd.sun.xml.writer.global", 0 },
+{ "sxi", 0, "application/vnd.sun.xml.impress", 0 },
+{ "sxm", 0, "application/vnd.sun.xml.math", 0 },
+{ "sxw", 0, "application/vnd.sun.xml.writer", 0 },
+{ "t", 0, "application/x-troff", 0 },
+{ "tar", 0, "application/x-tar", 0 },
+{ "tcl", 0, "application/x-tcl", 0 },
+{ "tex", 0, "application/x-tex", 0 },
+{ "texi", 0, "application/x-texinfo", 0 },
+{ "texinfo", 0, "application/x-texinfo", 0 },
+{ "tif", 0, "image/tiff", 0 },
+{ "tiff", 0, "image/tiff", 0 },
+{ "tr", 0, "application/x-troff", 0 },
+{ "tsp", 0, "application/dsptype", 0 },
+{ "tsv", 0, "text/tab-separated-values; charset=%s", 0 },
+{ "txt", 0, "text/plain; charset=%s", 0 },
+{ "ustar", 0, "application/x-ustar", 0 },
+{ "vcd", 0, "application/x-cdlink", 0 },
+{ "vrml", 0, "model/vrml", 0 },
+{ "vx", 0, "video/x-rad-screenplay", 0 },
+{ "wav", 0, "audio/x-wav", 0 },
+{ "wax", 0, "audio/x-ms-wax", 0 },
+{ "wbmp", 0, "image/vnd.wap.wbmp", 0 },
+{ "wbxml", 0, "application/vnd.wap.wbxml", 0 },
+{ "wm", 0, "video/x-ms-wm", 0 },
+{ "wma", 0, "audio/x-ms-wma", 0 },
+{ "wmd", 0, "application/x-ms-wmd", 0 },
+{ "wml", 0, "text/vnd.wap.wml", 0 },
+{ "wmlc", 0, "application/vnd.wap.wmlc", 0 },
+{ "wmls", 0, "text/vnd.wap.wmlscript", 0 },
+{ "wmlsc", 0, "application/vnd.wap.wmlscriptc", 0 },
+{ "wmv", 0, "video/x-ms-wmv", 0 },
+{ "wmx", 0, "video/x-ms-wmx", 0 },
+{ "wmz", 0, "application/x-ms-wmz", 0 },
+{ "wrl", 0, "model/vrml", 0 },
+{ "wsrc", 0, "application/x-wais-source", 0 },
+{ "wvx", 0, "video/x-ms-wvx", 0 },
+{ "xbm", 0, "image/x-xbitmap", 0 },
+{ "xht", 0, "application/xhtml+xml; charset=%s", 0 },
+{ "xhtml", 0, "application/xhtml+xml; charset=%s", 0 },
+{ "xls", 0, "application/vnd.ms-excel", 0 },
+{ "xml", 0, "text/xml; charset=%s", 0 },
+{ "xpm", 0, "image/x-xpixmap", 0 },
+{ "xsl", 0, "text/xml; charset=%s", 0 },
+{ "xwd", 0, "image/x-xwindowdump", 0 },
+{ "xyz", 0, "chemical/x-xyz", 0 },
+{ "zip", 0, "application/zip", 0 },
--- /dev/null
+# mime_types.txt
+#
+# A list of file extensions followed by the corresponding MIME type.
+# Extensions not found in the table are returned as text/plain.
+
+a application/octet-stream
+aab application/x-authorware-bin
+aam application/x-authorware-map
+aas application/x-authorware-seg
+ai application/postscript
+aif audio/x-aiff
+aifc audio/x-aiff
+aiff audio/x-aiff
+asc text/plain; charset=%s
+asf video/x-ms-asf
+asx video/x-ms-asf
+au audio/basic
+avi video/x-msvideo
+bcpio application/x-bcpio
+bin application/octet-stream
+bmp image/bmp
+cdf application/x-netcdf
+class application/x-java-vm
+cpio application/x-cpio
+cpt application/mac-compactpro
+crl application/x-pkcs7-crl
+crt application/x-x509-ca-cert
+csh application/x-csh
+css text/css; charset=%s
+dcr application/x-director
+dir application/x-director
+djv image/vnd.djvu
+djvu image/vnd.djvu
+dll application/octet-stream
+dms application/octet-stream
+doc application/msword
+dtd text/xml; charset=%s
+dump application/octet-stream
+dvi application/x-dvi
+dxr application/x-director
+eps application/postscript
+etx text/x-setext
+exe application/octet-stream
+ez application/andrew-inset
+fgd application/x-director
+fh image/x-freehand
+fh4 image/x-freehand
+fh5 image/x-freehand
+fh7 image/x-freehand
+fhc image/x-freehand
+gif image/gif
+gtar application/x-gtar
+hdf application/x-hdf
+hqx application/mac-binhex40
+htm text/html; charset=%s
+html text/html; charset=%s
+ice x-conference/x-cooltalk
+ief image/ief
+iges model/iges
+igs model/iges
+iv application/x-inventor
+jar application/x-java-archive
+jfif image/jpeg
+jpe image/jpeg
+jpeg image/jpeg
+jpg image/jpeg
+js application/x-javascript
+kar audio/midi
+kml application/vnd.google-earth.kml+xml
+kmz application/vnd.google-earth.kmz
+latex application/x-latex
+lha application/octet-stream
+loc application/xml-loc
+lzh application/octet-stream
+m3u audio/x-mpegurl
+man application/x-troff-man
+mathml application/mathml+xml
+me application/x-troff-me
+mesh model/mesh
+mid audio/midi
+midi audio/midi
+mif application/vnd.mif
+mime message/rfc822
+mml application/mathml+xml
+mov video/quicktime
+movie video/x-sgi-movie
+mp2 audio/mpeg
+mp3 audio/mpeg
+mp4 video/mp4
+mpe video/mpeg
+mpeg video/mpeg
+mpg video/mpeg
+mpga audio/mpeg
+ms application/x-troff-ms
+msh model/mesh
+mv video/x-sgi-movie
+mxu video/vnd.mpegurl
+nc application/x-netcdf
+o application/octet-stream
+oda application/oda
+ogg application/ogg
+pac application/x-ns-proxy-autoconfig
+pbm image/x-portable-bitmap
+pdb chemical/x-pdb
+pdf application/pdf
+pgm image/x-portable-graymap
+pgn application/x-chess-pgn
+png image/png
+pnm image/x-portable-anymap
+ppm image/x-portable-pixmap
+ppt application/vnd.ms-powerpoint
+ps application/postscript
+qt video/quicktime
+ra audio/x-realaudio
+ram audio/x-pn-realaudio
+ras image/x-cmu-raster
+rdf application/rdf+xml
+rgb image/x-rgb
+rm audio/x-pn-realaudio
+roff application/x-troff
+rpm audio/x-pn-realaudio-plugin
+rss application/rss+xml
+rtf text/rtf; charset=%s
+rtx text/richtext; charset=%s
+sgm text/sgml; charset=%s
+sgml text/sgml; charset=%s
+sh application/x-sh
+shar application/x-shar
+silo model/mesh
+sit application/x-stuffit
+skd application/x-koan
+skm application/x-koan
+skp application/x-koan
+skt application/x-koan
+smi application/smil
+smil application/smil
+snd audio/basic
+so application/octet-stream
+spl application/x-futuresplash
+src application/x-wais-source
+stc application/vnd.sun.xml.calc.template
+std application/vnd.sun.xml.draw.template
+sti application/vnd.sun.xml.impress.template
+stw application/vnd.sun.xml.writer.template
+sv4cpio application/x-sv4cpio
+sv4crc application/x-sv4crc
+svg image/svg+xml
+svgz image/svg+xml
+swf application/x-shockwave-flash
+sxc application/vnd.sun.xml.calc
+sxd application/vnd.sun.xml.draw
+sxg application/vnd.sun.xml.writer.global
+sxi application/vnd.sun.xml.impress
+sxm application/vnd.sun.xml.math
+sxw application/vnd.sun.xml.writer
+t application/x-troff
+tar application/x-tar
+tcl application/x-tcl
+tex application/x-tex
+texi application/x-texinfo
+texinfo application/x-texinfo
+tif image/tiff
+tiff image/tiff
+tr application/x-troff
+tsp application/dsptype
+tsv text/tab-separated-values; charset=%s
+txt text/plain; charset=%s
+ustar application/x-ustar
+vcd application/x-cdlink
+vrml model/vrml
+vx video/x-rad-screenplay
+wav audio/x-wav
+wax audio/x-ms-wax
+wbmp image/vnd.wap.wbmp
+wbxml application/vnd.wap.wbxml
+wm video/x-ms-wm
+wma audio/x-ms-wma
+wmd application/x-ms-wmd
+wml text/vnd.wap.wml
+wmlc application/vnd.wap.wmlc
+wmls text/vnd.wap.wmlscript
+wmlsc application/vnd.wap.wmlscriptc
+wmv video/x-ms-wmv
+wmx video/x-ms-wmx
+wmz application/x-ms-wmz
+wrl model/vrml
+wsrc application/x-wais-source
+wvx video/x-ms-wvx
+xbm image/x-xbitmap
+xht application/xhtml+xml; charset=%s
+xhtml application/xhtml+xml; charset=%s
+xls application/vnd.ms-excel
+xml text/xml; charset=%s
+xpm image/x-xpixmap
+xsl text/xml; charset=%s
+xwd image/x-xwindowdump
+xyz chemical/x-xyz
+zip application/zip
--- /dev/null
+/* mmc.c - mmap cache
+**
+** Copyright © 1998,2001,2014 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <errno.h>
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif /* HAVE_MMAP */
+
+#include "mmc.h"
+#include "libhttpd.h"
+
+#ifndef HAVE_INT64T
+typedef long long int64_t;
+#endif
+
+
+/* Defines. */
+#ifndef DEFAULT_EXPIRE_AGE
+#define DEFAULT_EXPIRE_AGE 600
+#endif
+#ifndef DESIRED_FREE_COUNT
+#define DESIRED_FREE_COUNT 100
+#endif
+#ifndef DESIRED_MAX_MAPPED_FILES
+#define DESIRED_MAX_MAPPED_FILES 2000
+#endif
+#ifndef DESIRED_MAX_MAPPED_BYTES
+#define DESIRED_MAX_MAPPED_BYTES 1000000000
+#endif
+#ifndef INITIAL_HASH_SIZE
+#define INITIAL_HASH_SIZE (1 << 10)
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+
+/* The Map struct. */
+typedef struct MapStruct {
+ ino_t ino;
+ dev_t dev;
+ off_t size;
+ time_t ct;
+ int refcount;
+ time_t reftime;
+ void* addr;
+ unsigned int hash;
+ int hash_idx;
+ struct MapStruct* next;
+ } Map;
+
+
+/* Globals. */
+static Map* maps = (Map*) 0;
+static Map* free_maps = (Map*) 0;
+static int alloc_count = 0, map_count = 0, free_count = 0;
+static Map** hash_table = (Map**) 0;
+static int hash_size;
+static unsigned int hash_mask;
+static time_t expire_age = DEFAULT_EXPIRE_AGE;
+static off_t mapped_bytes = 0;
+
+
+
+/* Forwards. */
+static void panic( void );
+static void really_unmap( Map** mm );
+static int check_hash_size( void );
+static int add_hash( Map* m );
+static Map* find_hash( ino_t ino, dev_t dev, off_t size, time_t ct );
+static unsigned int hash( ino_t ino, dev_t dev, off_t size, time_t ct );
+
+
+void*
+mmc_map( char* filename, struct stat* sbP, struct timeval* nowP )
+ {
+ time_t now;
+ struct stat sb;
+ Map* m;
+ int fd;
+
+ /* Stat the file, if necessary. */
+ if ( sbP != (struct stat*) 0 )
+ sb = *sbP;
+ else
+ {
+ if ( stat( filename, &sb ) != 0 )
+ {
+ syslog( LOG_ERR, "stat - %m" );
+ return (void*) 0;
+ }
+ }
+
+ /* Get the current time, if necessary. */
+ if ( nowP != (struct timeval*) 0 )
+ now = nowP->tv_sec;
+ else
+ now = time( (time_t*) 0 );
+
+ /* See if we have it mapped already, via the hash table. */
+ if ( check_hash_size() < 0 )
+ {
+ syslog( LOG_ERR, "check_hash_size() failure" );
+ return (void*) 0;
+ }
+ m = find_hash( sb.st_ino, sb.st_dev, sb.st_size, sb.st_ctime );
+ if ( m != (Map*) 0 )
+ {
+ /* Yep. Just return the existing map */
+ ++m->refcount;
+ m->reftime = now;
+ return m->addr;
+ }
+
+ /* Open the file. */
+ fd = open( filename, O_RDONLY );
+ if ( fd < 0 )
+ {
+ syslog( LOG_ERR, "open - %m" );
+ return (void*) 0;
+ }
+
+ /* Find a free Map entry or make a new one. */
+ if ( free_maps != (Map*) 0 )
+ {
+ m = free_maps;
+ free_maps = m->next;
+ --free_count;
+ }
+ else
+ {
+ m = (Map*) malloc( sizeof(Map) );
+ if ( m == (Map*) 0 )
+ {
+ (void) close( fd );
+ syslog( LOG_ERR, "out of memory allocating a Map" );
+ return (void*) 0;
+ }
+ ++alloc_count;
+ }
+
+ /* Fill in the Map entry. */
+ m->ino = sb.st_ino;
+ m->dev = sb.st_dev;
+ m->size = sb.st_size;
+ m->ct = sb.st_ctime;
+ m->refcount = 1;
+ m->reftime = now;
+
+ /* Avoid doing anything for zero-length files; some systems don't like
+ ** to mmap them, other systems dislike mallocing zero bytes.
+ */
+ if ( m->size == 0 )
+ m->addr = (void*) 1; /* arbitrary non-NULL address */
+ else
+ {
+ size_t size_size = (size_t) m->size; /* loses on files >2GB */
+#ifdef HAVE_MMAP
+ /* Map the file into memory. */
+ m->addr = mmap( 0, size_size, PROT_READ, MAP_PRIVATE, fd, 0 );
+ if ( m->addr == (void*) -1 && errno == ENOMEM )
+ {
+ /* Ooo, out of address space. Free all unreferenced maps
+ ** and try again.
+ */
+ panic();
+ m->addr = mmap( 0, size_size, PROT_READ, MAP_PRIVATE, fd, 0 );
+ }
+ if ( m->addr == (void*) -1 )
+ {
+ syslog( LOG_ERR, "mmap - %m" );
+ (void) close( fd );
+ free( (void*) m );
+ --alloc_count;
+ return (void*) 0;
+ }
+#else /* HAVE_MMAP */
+ /* Read the file into memory. */
+ m->addr = (void*) malloc( size_size );
+ if ( m->addr == (void*) 0 )
+ {
+ /* Ooo, out of memory. Free all unreferenced maps
+ ** and try again.
+ */
+ panic();
+ m->addr = (void*) malloc( size_size );
+ }
+ if ( m->addr == (void*) 0 )
+ {
+ syslog( LOG_ERR, "out of memory storing a file" );
+ (void) close( fd );
+ free( (void*) m );
+ --alloc_count;
+ return (void*) 0;
+ }
+ if ( httpd_read_fully( fd, m->addr, size_size ) != size_size )
+ {
+ syslog( LOG_ERR, "read - %m" );
+ (void) close( fd );
+ free( (void*) m );
+ --alloc_count;
+ return (void*) 0;
+ }
+#endif /* HAVE_MMAP */
+ }
+ (void) close( fd );
+
+ /* Put the Map into the hash table. */
+ if ( add_hash( m ) < 0 )
+ {
+ syslog( LOG_ERR, "add_hash() failure" );
+ free( (void*) m );
+ --alloc_count;
+ return (void*) 0;
+ }
+
+ /* Put the Map on the active list. */
+ m->next = maps;
+ maps = m;
+ ++map_count;
+
+ /* Update the total byte count. */
+ mapped_bytes += m->size;
+
+ /* And return the address. */
+ return m->addr;
+ }
+
+
+void
+mmc_unmap( void* addr, struct stat* sbP, struct timeval* nowP )
+ {
+ Map* m = (Map*) 0;
+
+ /* Find the Map entry for this address. First try a hash. */
+ if ( sbP != (struct stat*) 0 )
+ {
+ m = find_hash( sbP->st_ino, sbP->st_dev, sbP->st_size, sbP->st_ctime );
+ if ( m != (Map*) 0 && m->addr != addr )
+ m = (Map*) 0;
+ }
+ /* If that didn't work, try a full search. */
+ if ( m == (Map*) 0 )
+ for ( m = maps; m != (Map*) 0; m = m->next )
+ if ( m->addr == addr )
+ break;
+ if ( m == (Map*) 0 )
+ syslog( LOG_ERR, "mmc_unmap failed to find entry!" );
+ else if ( m->refcount <= 0 )
+ syslog( LOG_ERR, "mmc_unmap found zero or negative refcount!" );
+ else
+ {
+ --m->refcount;
+ if ( nowP != (struct timeval*) 0 )
+ m->reftime = nowP->tv_sec;
+ else
+ m->reftime = time( (time_t*) 0 );
+ }
+ }
+
+
+void
+mmc_cleanup( struct timeval* nowP )
+ {
+ time_t now;
+ Map** mm;
+ Map* m;
+
+ /* Get the current time, if necessary. */
+ if ( nowP != (struct timeval*) 0 )
+ now = nowP->tv_sec;
+ else
+ now = time( (time_t*) 0 );
+
+ /* Really unmap any unreferenced entries older than the age limit. */
+ for ( mm = &maps; *mm != (Map*) 0; )
+ {
+ m = *mm;
+ if ( m->refcount == 0 && now - m->reftime >= expire_age )
+ really_unmap( mm );
+ else
+ mm = &(*mm)->next;
+ }
+
+ /* Adjust the age limit if there are too many bytes mapped, or
+ ** too many or too few files mapped.
+ */
+ if ( mapped_bytes > DESIRED_MAX_MAPPED_BYTES )
+ expire_age = MAX( ( expire_age * 2 ) / 3, DEFAULT_EXPIRE_AGE / 10 );
+ else if ( map_count > DESIRED_MAX_MAPPED_FILES )
+ expire_age = MAX( ( expire_age * 2 ) / 3, DEFAULT_EXPIRE_AGE / 10 );
+ else if ( map_count < DESIRED_MAX_MAPPED_FILES / 2 )
+ expire_age = MIN( ( expire_age * 5 ) / 4, DEFAULT_EXPIRE_AGE * 3 );
+
+ /* Really free excess blocks on the free list. */
+ while ( free_count > DESIRED_FREE_COUNT )
+ {
+ m = free_maps;
+ free_maps = m->next;
+ --free_count;
+ free( (void*) m );
+ --alloc_count;
+ }
+ }
+
+
+static void
+panic( void )
+ {
+ Map** mm;
+ Map* m;
+
+ syslog( LOG_ERR, "mmc panic - freeing all unreferenced maps" );
+
+ /* Really unmap all unreferenced entries. */
+ for ( mm = &maps; *mm != (Map*) 0; )
+ {
+ m = *mm;
+ if ( m->refcount == 0 )
+ really_unmap( mm );
+ else
+ mm = &(*mm)->next;
+ }
+ }
+
+
+static void
+really_unmap( Map** mm )
+ {
+ Map* m;
+
+ m = *mm;
+ if ( m->size != 0 )
+ {
+#ifdef HAVE_MMAP
+ if ( munmap( m->addr, m->size ) < 0 )
+ syslog( LOG_ERR, "munmap - %m" );
+#else /* HAVE_MMAP */
+ free( (void*) m->addr );
+#endif /* HAVE_MMAP */
+ }
+ /* Update the total byte count. */
+ mapped_bytes -= m->size;
+ /* And move the Map to the free list. */
+ *mm = m->next;
+ --map_count;
+ m->next = free_maps;
+ free_maps = m;
+ ++free_count;
+ /* This will sometimes break hash chains, but that's harmless; the
+ ** unmapping code that searches the hash table knows to keep searching.
+ */
+ hash_table[m->hash_idx] = (Map*) 0;
+ }
+
+
+void
+mmc_term( void )
+ {
+ Map* m;
+
+ while ( maps != (Map*) 0 )
+ really_unmap( &maps );
+ while ( free_maps != (Map*) 0 )
+ {
+ m = free_maps;
+ free_maps = m->next;
+ --free_count;
+ free( (void*) m );
+ --alloc_count;
+ }
+ }
+
+
+/* Make sure the hash table is big enough. */
+static int
+check_hash_size( void )
+ {
+ int i;
+ Map* m;
+
+ /* Are we just starting out? */
+ if ( hash_table == (Map**) 0 )
+ {
+ hash_size = INITIAL_HASH_SIZE;
+ hash_mask = hash_size - 1;
+ }
+ /* Is it at least three times bigger than the number of entries? */
+ else if ( hash_size >= map_count * 3 )
+ return 0;
+ else
+ {
+ /* No, got to expand. */
+ free( (void*) hash_table );
+ /* Double the hash size until it's big enough. */
+ do
+ {
+ hash_size = hash_size << 1;
+ }
+ while ( hash_size < map_count * 6 );
+ hash_mask = hash_size - 1;
+ }
+ /* Make the new table. */
+ hash_table = (Map**) malloc( hash_size * sizeof(Map*) );
+ if ( hash_table == (Map**) 0 )
+ return -1;
+ /* Clear it. */
+ for ( i = 0; i < hash_size; ++i )
+ hash_table[i] = (Map*) 0;
+ /* And rehash all entries. */
+ for ( m = maps; m != (Map*) 0; m = m->next )
+ if ( add_hash( m ) < 0 )
+ return -1;
+ return 0;
+ }
+
+
+static int
+add_hash( Map* m )
+ {
+ unsigned int h, he, i;
+
+ h = hash( m->ino, m->dev, m->size, m->ct );
+ he = ( h + hash_size - 1 ) & hash_mask;
+ for ( i = h; ; i = ( i + 1 ) & hash_mask )
+ {
+ if ( hash_table[i] == (Map*) 0 )
+ {
+ hash_table[i] = m;
+ m->hash = h;
+ m->hash_idx = i;
+ return 0;
+ }
+ if ( i == he )
+ break;
+ }
+ return -1;
+ }
+
+
+static Map*
+find_hash( ino_t ino, dev_t dev, off_t size, time_t ct )
+ {
+ unsigned int h, he, i;
+ Map* m;
+
+ h = hash( ino, dev, size, ct );
+ he = ( h + hash_size - 1 ) & hash_mask;
+ for ( i = h; ; i = ( i + 1 ) & hash_mask )
+ {
+ m = hash_table[i];
+ if ( m == (Map*) 0 )
+ break;
+ if ( m->hash == h && m->ino == ino && m->dev == dev &&
+ m->size == size && m->ct == ct )
+ return m;
+ if ( i == he )
+ break;
+ }
+ return (Map*) 0;
+ }
+
+
+static unsigned int
+hash( ino_t ino, dev_t dev, off_t size, time_t ct )
+ {
+ unsigned int h = 177573;
+
+ h ^= ino;
+ h += h << 5;
+ h ^= dev;
+ h += h << 5;
+ h ^= size;
+ h += h << 5;
+ h ^= ct;
+
+ return h & hash_mask;
+ }
+
+
+/* Generate debugging statistics syslog message. */
+void
+mmc_logstats( long secs )
+ {
+ syslog(
+ LOG_NOTICE, " map cache - %d allocated, %d active (%lld bytes), %d free; hash size: %d; expire age: %lld",
+ alloc_count, map_count, (long long) mapped_bytes, free_count, hash_size,
+ (long long) expire_age );
+ if ( map_count + free_count != alloc_count )
+ syslog( LOG_ERR, "map counts don't add up!" );
+ }
--- /dev/null
+/* mmc.h - header file for mmap cache package
+**
+** Copyright © 1998,2014 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#ifndef _MMC_H_
+#define _MMC_H_
+
+/* Returns an mmap()ed area for the given file, or (void*) 0 on errors.
+** If you have a stat buffer on the file, pass it in, otherwise pass 0.
+** Same for the current time.
+*/
+void* mmc_map( char* filename, struct stat* sbP, struct timeval* nowP );
+
+/* Done with an mmap()ed area that was returned by mmc_map().
+** If you have a stat buffer on the file, pass it in, otherwise pass 0.
+** Same for the current time.
+*/
+void mmc_unmap( void* addr, struct stat* sbP, struct timeval* nowP );
+
+/* Clean up the mmc package, freeing any unused storage.
+** This should be called periodically, say every five minutes.
+** If you have the current time, pass it in, otherwise pass 0.
+*/
+void mmc_cleanup( struct timeval* nowP );
+
+/* Free all storage, usually in preparation for exitting. */
+void mmc_term( void );
+
+/* Generate debugging statistics syslog message. */
+void mmc_logstats( long secs );
+
+#endif /* _MMC_H_ */
--- /dev/null
+#!/bin/sh
+#
+# thttpd-rotate - nightly script to rotate thttpd's log files on FreeBSD
+#
+# This goes in /etc/periodic/daily. It rotates the log files and then
+# tells thttpd to re-open its log file.
+
+cd /usr/local/www/chroot/logs
+rm -f thttpd_log.7.gz
+mv thttpd_log.6.gz thttpd_log.7.gz
+mv thttpd_log.5.gz thttpd_log.6.gz
+mv thttpd_log.4.gz thttpd_log.5.gz
+mv thttpd_log.3.gz thttpd_log.4.gz
+mv thttpd_log.2.gz thttpd_log.3.gz
+mv thttpd_log.1.gz thttpd_log.2.gz
+mv thttpd_log thttpd_log.1
+kill -HUP `cat /var/run/thttpd.pid`
+sleep 1
+gzip -f thttpd_log.1
--- /dev/null
+#!/bin/sh
+#
+# thttpd.sh - startup script for thttpd on FreeBSD
+#
+# This should be manually installed as:
+# /usr/local/etc/rc.d/thttpd
+# It gets run at boot-time.
+#
+# Variables available:
+# thttpd_enable='YES'
+# thttpd_program='/usr/local/sbin/thttpd'
+# thttpd_pidfile='/var/run/thttpd.pid'
+# thttpd_devfs=...
+# thttpd_flags=...
+#
+# PROVIDE: thttpd
+# REQUIRE: LOGIN FILESYSTEMS
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name='thttpd'
+rcvar='thttpd_enable'
+start_precmd='thttpd_precmd'
+stop_cmd='thttpd_stop'
+thttpd_enable_defval='NO'
+
+load_rc_config "$name"
+command="${thttpd_program:-/usr/local/sbin/${name}}"
+pidfile="${thttpd_pidfile:-/var/run/${name}.pid}"
+command_args="-i ${pidfile}"
+
+thttpd_precmd ()
+{
+ if [ -n "$thttpd_devfs" ] ; then
+ mount -t devfs devfs "$thttpd_devfs"
+ devfs -m "$thttpd_devfs" rule -s 1 applyset
+ devfs -m "$thttpd_devfs" rule -s 2 applyset
+ fi
+}
+
+thttpd_stop ()
+{
+ kill -USR1 `cat "$pidfile"`
+}
+
+run_rc_command "$1"
--- /dev/null
+#!/bin/sh
+#
+# thttpd_wrapper - wrapper script for thttpd on FreeBSD
+#
+# This goes in /usr/local/sbin. It backgrounds itself, and then runs
+# thttpd in a loop. If thttpd exits then the script restarts it automatically.
+#
+# The -D flag tells thttpd to *not* put itself into the background,
+# and the -C flag tells it to get the rest of its configuration from
+# the specified config file.
+
+(
+ while true ; do
+ /usr/local/sbin/thttpd -D -C /usr/local/www/thttpd_config
+ if [ -f /var/run/nologin ] ; then
+ exit
+ fi
+ sleep 10
+ egrep ' thttpd[:\[]' /var/log/messages |
+ tail -33 |
+ mail -s "thttpd on `hostname` restarted" root
+ done
+) &
--- /dev/null
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strerror.c 5.1 (Berkeley) 4/9/89";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+char *
+strerror(errnum)
+ int errnum;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ static char ebuf[20];
+
+ if ((unsigned int)errnum < sys_nerr)
+ return(sys_errlist[errnum]);
+ (void)sprintf(ebuf, "Unknown error: %d", errnum);
+ return(ebuf);
+}
--- /dev/null
+/* tdate_parse - parse string dates into internal form, stripped-down version
+**
+** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+/* This is a stripped-down version of date_parse.c, available at
+** http://www.acme.com/software/date_parse/
+*/
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "tdate_parse.h"
+
+
+struct strlong {
+ char* s;
+ long l;
+ };
+
+
+static void
+pound_case( char* str )
+ {
+ for ( ; *str != '\0'; ++str )
+ {
+ if ( isupper( (int) *str ) )
+ *str = tolower( (int) *str );
+ }
+ }
+
+
+static int
+strlong_compare( const void* v1, const void* v2 )
+ {
+ const struct strlong* s1 = (const struct strlong*) v1;
+ const struct strlong* s2 = (const struct strlong*) v2;
+ return strcmp( s1->s, s2->s );
+ }
+
+
+static int
+strlong_search( char* str, struct strlong* tab, int n, long* lP )
+ {
+ int i, h, l, r;
+
+ l = 0;
+ h = n - 1;
+ for (;;)
+ {
+ i = ( h + l ) / 2;
+ r = strcmp( str, tab[i].s );
+ if ( r < 0 )
+ h = i - 1;
+ else if ( r > 0 )
+ l = i + 1;
+ else
+ {
+ *lP = tab[i].l;
+ return 1;
+ }
+ if ( h < l )
+ return 0;
+ }
+ }
+
+
+static int
+scan_wday( char* str_wday, long* tm_wdayP )
+ {
+ static struct strlong wday_tab[] = {
+ { "sun", 0 }, { "sunday", 0 },
+ { "mon", 1 }, { "monday", 1 },
+ { "tue", 2 }, { "tuesday", 2 },
+ { "wed", 3 }, { "wednesday", 3 },
+ { "thu", 4 }, { "thursday", 4 },
+ { "fri", 5 }, { "friday", 5 },
+ { "sat", 6 }, { "saturday", 6 },
+ };
+ static int sorted = 0;
+
+ if ( ! sorted )
+ {
+ (void) qsort(
+ wday_tab, sizeof(wday_tab)/sizeof(struct strlong),
+ sizeof(struct strlong), strlong_compare );
+ sorted = 1;
+ }
+ pound_case( str_wday );
+ return strlong_search(
+ str_wday, wday_tab, sizeof(wday_tab)/sizeof(struct strlong), tm_wdayP );
+ }
+
+
+static int
+scan_mon( char* str_mon, long* tm_monP )
+ {
+ static struct strlong mon_tab[] = {
+ { "jan", 0 }, { "january", 0 },
+ { "feb", 1 }, { "february", 1 },
+ { "mar", 2 }, { "march", 2 },
+ { "apr", 3 }, { "april", 3 },
+ { "may", 4 },
+ { "jun", 5 }, { "june", 5 },
+ { "jul", 6 }, { "july", 6 },
+ { "aug", 7 }, { "august", 7 },
+ { "sep", 8 }, { "september", 8 },
+ { "oct", 9 }, { "october", 9 },
+ { "nov", 10 }, { "november", 10 },
+ { "dec", 11 }, { "december", 11 },
+ };
+ static int sorted = 0;
+
+ if ( ! sorted )
+ {
+ (void) qsort(
+ mon_tab, sizeof(mon_tab)/sizeof(struct strlong),
+ sizeof(struct strlong), strlong_compare );
+ sorted = 1;
+ }
+ pound_case( str_mon );
+ return strlong_search(
+ str_mon, mon_tab, sizeof(mon_tab)/sizeof(struct strlong), tm_monP );
+ }
+
+
+static int
+is_leap( int year )
+ {
+ return year % 400? ( year % 100 ? ( year % 4 ? 0 : 1 ) : 0 ) : 1;
+ }
+
+
+/* Basically the same as mktime(). */
+static time_t
+tm_to_time( struct tm* tmP )
+ {
+ time_t t;
+ static int monthtab[12] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+ /* Years since epoch, converted to days. */
+ t = ( tmP->tm_year - 70 ) * 365;
+ /* Leap days for previous years - this will break in 2100! */
+ t += ( tmP->tm_year - 69 ) / 4;
+ /* Days for the beginning of this month. */
+ t += monthtab[tmP->tm_mon];
+ /* Leap day for this year. */
+ if ( tmP->tm_mon >= 2 && is_leap( tmP->tm_year + 1900 ) )
+ ++t;
+ /* Days since the beginning of this month. */
+ t += tmP->tm_mday - 1; /* 1-based field */
+ /* Hours, minutes, and seconds. */
+ t = t * 24 + tmP->tm_hour;
+ t = t * 60 + tmP->tm_min;
+ t = t * 60 + tmP->tm_sec;
+
+ return t;
+ }
+
+
+time_t
+tdate_parse( char* str )
+ {
+ struct tm tm;
+ char* cp;
+ char str_mon[500], str_wday[500];
+ int tm_sec, tm_min, tm_hour, tm_mday, tm_year;
+ long tm_mon, tm_wday;
+ time_t t;
+
+ /* Initialize. */
+ (void) memset( (char*) &tm, 0, sizeof(struct tm) );
+
+ /* Skip initial whitespace ourselves - sscanf is clumsy at this. */
+ for ( cp = str; *cp == ' ' || *cp == '\t'; ++cp )
+ continue;
+
+ /* And do the sscanfs. WARNING: you can add more formats here,
+ ** but be careful! You can easily screw up the parsing of existing
+ ** formats when you add new ones. The order is important.
+ */
+
+ /* DD-mth-YY HH:MM:SS GMT */
+ if ( sscanf( cp, "%d-%400[a-zA-Z]-%d %d:%d:%d GMT",
+ &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
+ &tm_sec ) == 6 &&
+ scan_mon( str_mon, &tm_mon ) )
+ {
+ tm.tm_mday = tm_mday;
+ tm.tm_mon = tm_mon;
+ tm.tm_year = tm_year;
+ tm.tm_hour = tm_hour;
+ tm.tm_min = tm_min;
+ tm.tm_sec = tm_sec;
+ }
+
+ /* DD mth YY HH:MM:SS GMT */
+ else if ( sscanf( cp, "%d %400[a-zA-Z] %d %d:%d:%d GMT",
+ &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
+ &tm_sec) == 6 &&
+ scan_mon( str_mon, &tm_mon ) )
+ {
+ tm.tm_mday = tm_mday;
+ tm.tm_mon = tm_mon;
+ tm.tm_year = tm_year;
+ tm.tm_hour = tm_hour;
+ tm.tm_min = tm_min;
+ tm.tm_sec = tm_sec;
+ }
+
+ /* HH:MM:SS GMT DD-mth-YY */
+ else if ( sscanf( cp, "%d:%d:%d GMT %d-%400[a-zA-Z]-%d",
+ &tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon,
+ &tm_year ) == 6 &&
+ scan_mon( str_mon, &tm_mon ) )
+ {
+ tm.tm_hour = tm_hour;
+ tm.tm_min = tm_min;
+ tm.tm_sec = tm_sec;
+ tm.tm_mday = tm_mday;
+ tm.tm_mon = tm_mon;
+ tm.tm_year = tm_year;
+ }
+
+ /* HH:MM:SS GMT DD mth YY */
+ else if ( sscanf( cp, "%d:%d:%d GMT %d %400[a-zA-Z] %d",
+ &tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon,
+ &tm_year ) == 6 &&
+ scan_mon( str_mon, &tm_mon ) )
+ {
+ tm.tm_hour = tm_hour;
+ tm.tm_min = tm_min;
+ tm.tm_sec = tm_sec;
+ tm.tm_mday = tm_mday;
+ tm.tm_mon = tm_mon;
+ tm.tm_year = tm_year;
+ }
+
+ /* wdy, DD-mth-YY HH:MM:SS GMT */
+ else if ( sscanf( cp, "%400[a-zA-Z], %d-%400[a-zA-Z]-%d %d:%d:%d GMT",
+ str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
+ &tm_sec ) == 7 &&
+ scan_wday( str_wday, &tm_wday ) &&
+ scan_mon( str_mon, &tm_mon ) )
+ {
+ tm.tm_wday = tm_wday;
+ tm.tm_mday = tm_mday;
+ tm.tm_mon = tm_mon;
+ tm.tm_year = tm_year;
+ tm.tm_hour = tm_hour;
+ tm.tm_min = tm_min;
+ tm.tm_sec = tm_sec;
+ }
+
+ /* wdy, DD mth YY HH:MM:SS GMT */
+ else if ( sscanf( cp, "%400[a-zA-Z], %d %400[a-zA-Z] %d %d:%d:%d GMT",
+ str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
+ &tm_sec ) == 7 &&
+ scan_wday( str_wday, &tm_wday ) &&
+ scan_mon( str_mon, &tm_mon ) )
+ {
+ tm.tm_wday = tm_wday;
+ tm.tm_mday = tm_mday;
+ tm.tm_mon = tm_mon;
+ tm.tm_year = tm_year;
+ tm.tm_hour = tm_hour;
+ tm.tm_min = tm_min;
+ tm.tm_sec = tm_sec;
+ }
+
+ /* wdy mth DD HH:MM:SS GMT YY */
+ else if ( sscanf( cp, "%400[a-zA-Z] %400[a-zA-Z] %d %d:%d:%d GMT %d",
+ str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec,
+ &tm_year ) == 7 &&
+ scan_wday( str_wday, &tm_wday ) &&
+ scan_mon( str_mon, &tm_mon ) )
+ {
+ tm.tm_wday = tm_wday;
+ tm.tm_mon = tm_mon;
+ tm.tm_mday = tm_mday;
+ tm.tm_hour = tm_hour;
+ tm.tm_min = tm_min;
+ tm.tm_sec = tm_sec;
+ tm.tm_year = tm_year;
+ }
+ else
+ return (time_t) -1;
+
+ if ( tm.tm_year > 1900 )
+ tm.tm_year -= 1900;
+ else if ( tm.tm_year < 70 )
+ tm.tm_year += 100;
+
+ t = tm_to_time( &tm );
+
+ return t;
+ }
--- /dev/null
+/* tdate_parse.h - parse string dates into internal form, stripped-down version
+**
+** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#ifndef _TDATE_PARSE_H_
+#define _TDATE_PARSE_H_
+
+time_t tdate_parse( char* str );
+
+#endif /* _TDATE_PARSE_H_ */
--- /dev/null
+.TH thttpd 8 "29 February 2000"
+.SH NAME
+thttpd - tiny/turbo/throttling HTTP server
+.SH SYNOPSIS
+.B thttpd
+.RB [ -C
+.IR configfile ]
+.RB [ -p
+.IR port ]
+.RB [ -d
+.IR dir ]
+.RB [ -dd
+.IR data_dir ]
+.RB [ -r | -nor ]
+.RB [ -s | -nos ]
+.RB [ -v | -nov ]
+.RB [ -g | -nog ]
+.RB [ -u
+.IR user ]
+.RB [ -c
+.IR cgipat ]
+.RB [ -t
+.IR throttles ]
+.RB [ -h
+.IR host ]
+.RB [ -l
+.IR logfile ]
+.RB [ -i
+.IR pidfile ]
+.RB [ -T
+.IR charset ]
+.RB [ -P
+.IR P3P ]
+.RB [ -M
+.IR maxage ]
+.RB [ -V ]
+.RB [ -D ]
+.SH DESCRIPTION
+.PP
+.I thttpd
+is a simple, small, fast, and secure HTTP server.
+It doesn't have a lot of special features, but it suffices for most uses of
+the web, it's about as fast as the best full-featured servers (Apache, NCSA,
+Netscape),
+and it has one extremely useful feature (URL-traffic-based throttling)
+that no other server currently has.
+.SH OPTIONS
+.TP
+.B -C
+Specifies a config-file to read.
+All options can be set either by command-line flags or in the config file.
+See below for details.
+.TP
+.B -p
+Specifies an alternate port number to listen on.
+The default is 80.
+The config-file option name for this flag is "port",
+and the config.h option is DEFAULT_PORT.
+.TP
+.B -d
+Specifies a directory to chdir() to at startup.
+This is merely a convenience - you could just as easily
+do a cd in the shell script that invokes the program.
+The config-file option name for this flag is "dir",
+and the config.h options are WEBDIR, USE_USER_DIR.
+.TP
+.B -r
+Do a chroot() at initialization time, restricting file access
+to the program's current directory.
+If -r is the compiled-in default, then -nor disables it.
+See below for details.
+The config-file option names for this flag are "chroot" and "nochroot",
+and the config.h option is ALWAYS_CHROOT.
+.TP
+.B -dd
+Specifies a directory to chdir() to after chrooting.
+If you're not chrooting, you might as well do a single chdir() with
+the -d flag.
+If you are chrooting, this lets you put the web files in a subdirectory
+of the chroot tree, instead of in the top level mixed in with the
+chroot files.
+The config-file option name for this flag is "data_dir".
+.TP
+.B -nos
+Don't do explicit symbolic link checking.
+Normally, thttpd explicitly expands any symbolic links in filenames,
+to check that the resulting path stays within the original document tree.
+If you want to turn off this check and save some CPU time, you can use
+the -nos flag, however this is not recommended.
+Note, though, that if you are using the chroot option, the symlink
+checking is unnecessary and is turned off, so the safe way to save
+those CPU cycles is to use chroot.
+The config-file option names for this flag are "symlinkcheck" and "nosymlinkcheck".
+.TP
+.B -v
+Do el-cheapo virtual hosting.
+If -v is the compiled-in default, then -nov disables it.
+See below for details.
+The config-file option names for this flag are "vhost" and "novhost",
+and the config.h option is ALWAYS_VHOST.
+.TP
+.B -g
+Use a global passwd file.
+This means that every file in the entire document tree is protected by
+the single .htpasswd file at the top of the tree.
+Otherwise the semantics of the .htpasswd file are the same.
+If this option is set but there is no .htpasswd file in
+the top-level directory, then thttpd proceeds as if the option was
+not set - first looking for a local .htpasswd file, and if that doesn't
+exist either then serving the file without any password.
+If -g is the compiled-in default, then -nog disables it.
+The config-file option names for this flag are "globalpasswd" and
+"noglobalpasswd",
+and the config.h option is ALWAYS_GLOBAL_PASSWD.
+.TP
+.B -u
+Specifies what user to switch to after initialization when started as root.
+The default is "nobody".
+The config-file option name for this flag is "user",
+and the config.h option is DEFAULT_USER.
+.TP
+.B -c
+Specifies a wildcard pattern for CGI programs, for instance "**.cgi"
+or "/cgi-bin/*".
+See below for details.
+The config-file option name for this flag is "cgipat",
+and the config.h option is CGI_PATTERN.
+.TP
+.B -t
+Specifies a file of throttle settings.
+See below for details.
+The config-file option name for this flag is "throttles".
+.TP
+.B -h
+Specifies a hostname to bind to, for multihoming.
+The default is to bind to all hostnames supported on the local machine.
+See below for details.
+The config-file option name for this flag is "host",
+and the config.h option is SERVER_NAME.
+.TP
+.B -l
+Specifies a file for logging.
+If no -l argument is specified, thttpd logs via syslog().
+If "-l /dev/null" is specified, thttpd doesn't log at all.
+The config-file option name for this flag is "logfile".
+.TP
+.B -i
+Specifies a file to write the process-id to.
+If no file is specified, no process-id is written.
+You can use this file to send signals to thttpd.
+See below for details.
+The config-file option name for this flag is "pidfile".
+.TP
+.B -T
+Specifies the character set to use with text MIME types.
+The default is UTF-8.
+The config-file option name for this flag is "charset",
+and the config.h option is DEFAULT_CHARSET.
+.TP
+.B -P
+Specifies a P3P server privacy header to be returned with all responses.
+See http://www.w3.org/P3P/ for details.
+Thttpd doesn't do anything at all with the string except put it in the
+P3P: response header.
+The config-file option name for this flag is "p3p".
+.TP
+.B -M
+Specifies the number of seconds to be used in a "Cache-Control: max-age"
+header to be returned with all responses.
+An equivalent "Expires" header is also generated.
+The default is no Cache-Control or Expires headers,
+which is just fine for most sites.
+The config-file option name for this flag is "max_age".
+.TP
+.B -V
+Shows the current version info.
+.TP
+.B -D
+This was originally just a debugging flag, however it's worth mentioning
+because one of the things it does is prevent thttpd from making itself
+a background daemon.
+Instead it runs in the foreground like a regular program.
+This is necessary when you want to run thttpd wrapped in a little shell
+script that restarts it if it exits.
+.SH "CONFIG-FILE"
+.PP
+All the command-line options can also be set in a config file.
+One advantage of using a config file is that the file can be changed,
+and thttpd will pick up the changes with a restart.
+.PP
+The syntax of the config file is simple, a series of "option" or
+"option=value" separated by whitespace.
+The option names are listed above with their corresponding command-line flags.
+.SH "CHROOT"
+.PP
+chroot() is a system call that restricts the program's view
+of the filesystem to the current directory and directories
+below it.
+It becomes impossible for remote users to access any file
+outside of the initial directory.
+The restriction is inherited by child processes, so CGI programs get it too.
+This is a very strong security measure, and is recommended.
+The only downside is that only root can call chroot(), so this means
+the program must be started as root.
+However, the last thing it does during initialization is to
+give up root access by becoming another user, so this is safe.
+.PP
+The program can also be compile-time configured to always
+do a chroot(), without needing the -r flag.
+.PP
+Note that with some other web servers, such as NCSA httpd, setting
+up a directory tree for use with chroot() is complicated, involving
+creating a bunch of special directories and copying in various files.
+With thttpd it's a lot easier, all you have to do is make sure
+any shells, utilities, and config files used by your CGI programs and
+scripts are available.
+If you have CGI disabled, or if you make a policy that all CGI programs
+must be written in a compiled language such as C and statically linked,
+then you probably don't have to do any setup at all.
+.PP
+However, one thing you should do is tell syslogd about the chroot tree,
+so that thttpd can still generate syslog messages.
+Check your system's syslodg man page for how to do this.
+In FreeBSD you would put something like this in /etc/rc.conf:
+.nf
+ syslogd_flags="-l /usr/local/www/data/dev/log"
+.fi
+Substitute in your own chroot tree's pathname, of course.
+Don't worry about creating the log socket, syslogd wants to do that itself.
+(You may need to create the dev directory.)
+In Linux the flag is -a instead of -l, and there may be other differences.
+.PP
+Relevant config.h option: ALWAYS_CHROOT.
+.SH "CGI"
+.PP
+thttpd supports the CGI 1.1 spec.
+.PP
+In order for a CGI program to be run, its name must match the pattern
+specified either at compile time or on the command line with the -c flag.
+This is a simple shell-style filename pattern.
+You can use * to match any string not including a slash,
+or ** to match any string including slashes,
+or ? to match any single character.
+You can also use multiple such patterns separated by |.
+The patterns get checked against the filename
+part of the incoming URL.
+Don't forget to quote any wildcard characters so that the shell doesn't
+mess with them.
+.PP
+Restricting CGI programs to a single directory lets the site administrator
+review them for security holes, and is strongly recommended.
+If there are individual users that you trust, you can enable their
+directories too.
+.PP
+If no CGI pattern is specified, neither here nor at compile time,
+then CGI programs cannot be run at all.
+If you want to disable CGI as a security measure, that's how you do it, just
+comment out the patterns in the config file and don't run with the -c flag.
+.PP
+Note: the current working directory when a CGI program gets run is
+the directory that the CGI program lives in.
+This isn't in the CGI 1.1 spec, but it's what most other HTTP servers do.
+.PP
+Relevant config.h options: CGI_PATTERN, CGI_TIMELIMIT, CGI_NICE, CGI_PATH, CGI_LD_LIBRARY_PATH, CGIBINDIR.
+.SH "BASIC AUTHENTICATION"
+.PP
+Basic Authentication is available as an option at compile time.
+If enabled, it uses a password file in the directory to be protected,
+called .htpasswd by default.
+This file is formatted as the familiar colon-separated
+username/encrypted-password pair, records delimited by newlines.
+The protection does not carry over to subdirectories.
+The utility program htpasswd(1) is included to help create and
+modify .htpasswd files.
+.PP
+Relevant config.h option: AUTH_FILE
+.SH "THROTTLING"
+.PP
+The throttle file lets you set maximum byte rates on URLs or URL groups.
+You can optionally set a minimum rate too.
+The format of the throttle file is very simple.
+A # starts a comment, and the rest of the line is ignored.
+Blank lines are ignored.
+The rest of the lines should consist of a pattern, whitespace, and a number.
+The pattern is a simple shell-style filename pattern, using ?/**/*, or
+multiple such patterns separated by |.
+.PP
+The numbers in the file are byte rates, specified in units of bytes per second.
+For comparison, a v.90 modem gives about 5000 B/s depending on compression,
+a double-B-channel ISDN line about 12800 B/s, and a T1 line is about
+150000 B/s.
+If you want to set a minimum rate as well, use number-number.
+.PP
+Example:
+.nf
+ # throttle file for www.acme.com
+
+ ** 2000-100000 # limit total web usage to 2/3 of our T1,
+ # but never go below 2000 B/s
+ **.jpg|**.gif 50000 # limit images to 1/3 of our T1
+ **.mpg 20000 # and movies to even less
+ jef/** 20000 # jef's pages are too popular
+.fi
+.PP
+Throttling is implemented by checking each incoming URL filename against all
+of the patterns in the throttle file.
+The server accumulates statistics on how much bandwidth each pattern
+has accounted for recently (via a rolling average).
+If a URL matches a pattern that has been exceeding its specified limit,
+then the data returned is actually slowed down, with
+pauses between each block.
+If that's not possible (e.g. for CGI programs) or if the bandwidth has gotten
+way larger than the limit, then the server returns a special code
+saying 'try again later'.
+.PP
+The minimum rates are implemented similarly.
+If too many people are trying to fetch something at the same time,
+throttling may slow down each connection so much that it's not really
+useable.
+Furthermore, all those slow connections clog up the server, using
+up file handles and connection slots.
+Setting a minimum rate says that past a certain point you should not
+even bother - the server returns the 'try again later" code and the
+connection isn't even started.
+.PP
+There is no provision for setting a maximum connections/second throttle,
+because throttling a request uses as much cpu as handling it, so
+there would be no point.
+There is also no provision for throttling the number of simultaneous
+connections on a per-URL basis.
+However you can control the overall number of connections for the whole
+server very simply, by setting the operating system's per-process file
+descriptor limit before starting thttpd.
+Be sure to set the hard limit, not the soft limit.
+.SH "MULTIHOMING"
+.PP
+Multihoming means using one machine to serve multiple hostnames.
+For instance, if you're an internet provider and you want to let
+all of your customers have customized web addresses, you might
+have www.joe.acme.com, www.jane.acme.com, and your own www.acme.com,
+all running on the same physical hardware.
+This feature is also known as "virtual hosts".
+There are three steps to setting this up.
+.PP
+One, make DNS entries for all of the hostnames.
+The current way to do this, allowed by HTTP/1.1, is to use CNAME aliases,
+like so:
+.nf
+ www.acme.com IN A 192.100.66.1
+ www.joe.acme.com IN CNAME www.acme.com
+ www.jane.acme.com IN CNAME www.acme.com
+.fi
+However, this is incompatible with older HTTP/1.0 browsers.
+If you want to stay compatible, there's a different way - use A records
+instead, each with a different IP address, like so:
+.nf
+ www.acme.com IN A 192.100.66.1
+ www.joe.acme.com IN A 192.100.66.200
+ www.jane.acme.com IN A 192.100.66.201
+.fi
+This is bad because it uses extra IP addresses, a somewhat scarce resource.
+But if you want people with older browsers to be able to visit your
+sites, you still have to do it this way.
+.PP
+Step two.
+If you're using the modern CNAME method of multihoming, then you can
+skip this step.
+Otherwise, using the older multiple-IP-address method you
+must set up IP aliases or multiple interfaces for the extra addresses.
+You can use ifconfig(8)'s alias command to tell the machine to answer to
+all of the different IP addresses.
+Example:
+.nf
+ ifconfig le0 www.acme.com
+ ifconfig le0 www.joe.acme.com alias
+ ifconfig le0 www.jane.acme.com alias
+.fi
+If your OS's version of ifconfig doesn't have an alias command, you're
+probably out of luck (but see http://www.acme.com/software/thttpd/notes.html).
+.PP
+Third and last, you must set up thttpd to handle the multiple hosts.
+The easiest way is with the -v flag, or the ALWAYS_VHOST config.h option.
+This works with either CNAME multihosting or multiple-IP multihosting.
+What it does is send each incoming request to a subdirectory based on the
+hostname it's intended for.
+All you have to do in order to set things up is to create those subdirectories
+in the directory where thttpd will run.
+With the example above, you'd do like so:
+.nf
+ mkdir www.acme.com www.joe.acme.com www.jane.acme.com
+.fi
+If you're using old-style multiple-IP multihosting, you should also create
+symbolic links from the numeric addresses to the names, like so:
+.nf
+ ln -s www.acme.com 192.100.66.1
+ ln -s www.joe.acme.com 192.100.66.200
+ ln -s www.jane.acme.com 192.100.66.201
+.fi
+This lets the older HTTP/1.0 browsers find the right subdirectory.
+.PP
+There's an optional alternate step three if you're using multiple-IP
+multihosting: run a separate thttpd process for each hostname, using
+the -h flag to specify which one is which.
+This gives you more flexibility, since you can run each of these processes
+in separate directories, with different throttle files, etc.
+Example:
+.nf
+ thttpd -r -d /usr/www -h www.acme.com
+ thttpd -r -d /usr/www/joe -u joe -h www.joe.acme.com
+ thttpd -r -d /usr/www/jane -u jane -h www.jane.acme.com
+.fi
+But remember, this multiple-process method does not work with CNAME
+multihosting - for that, you must use a single thttpd process with
+the -v flag.
+.SH "CUSTOM ERRORS"
+.PP
+thttpd lets you define your own custom error pages for the various
+HTTP errors.
+There's a separate file for each error number, all stored in one
+special directory.
+The directory name is "errors", at the top of the web directory tree.
+The error files should be named "errNNN.html", where NNN is the error number.
+So for example, to make a custom error page for the authentication failure
+error, which is number 401, you would put your HTML into the file
+"errors/err401.html".
+If no custom error file is found for a given error number, then the
+usual built-in error page is generated.
+.PP
+If you're using the virtual hosts option, you can also have different
+custom error pages for each different virtual host.
+In this case you put another "errors" directory in the top of that
+virtual host's web tree.
+thttpd will look first in the virtual host errors directory, and
+then in the server-wide errors directory, and if neither of those
+has an appropriate error file then it will generate the built-in error.
+.SH "NON-LOCAL REFERRERS"
+.PP
+Sometimes another site on the net will embed your image files in their
+HTML files, which basically means they're stealing your bandwidth.
+You can prevent them from doing this by using non-local referrer filtering.
+With this option, certain files can only be fetched via a local referrer.
+The files have to be referenced by a local web page.
+If a web page on some other site references the files, that fetch will
+be blocked.
+There are three config-file variables for this feature:
+.TP
+.B urlpat
+A wildcard pattern for the URLs that should require a local referrer.
+This is typically just image files, sound files, and so on.
+For example:
+.nf
+ urlpat=**.jpg|**.gif|**.au|**.wav
+.fi
+For most sites, that one setting is all you need to enable referrer filtering.
+.TP
+.B noemptyreferrers
+By default, requests with no referrer at all, or a null referrer, or a
+referrer with no apparent hostname, are allowed.
+With this variable set, such requests are disallowed.
+.TP
+.B localpat
+A wildcard pattern that specifies the local host or hosts.
+This is used to determine if the host in the referrer is local or not.
+If not specified it defaults to the actual local hostname.
+.SH SYMLINKS
+.PP
+thttpd is very picky about symbolic links.
+Before delivering any file, it first checks each element in the path
+to see if it's a symbolic link, and expands them all out to get the final
+actual filename.
+Along the way it checks for things like links with ".." that go above
+the server's directory, and absolute symlinks (ones that start with a /).
+These are prohibited as security holes, so the server returns an
+error page for them.
+This means you can't set up your web directory with a bunch of symlinks
+pointing to individual users' home web directories.
+Instead you do it the other way around - the user web directories are
+real subdirs of the main web directory, and in each user's home
+dir there's a symlink pointing to their actual web dir.
+.PP
+The CGI pattern is also affected - it gets matched against the fully-expanded
+filename. So, if you have a single CGI directory but then put a symbolic
+link in it pointing somewhere else, that won't work. The CGI program will be
+treated as a regular file and returned to the client, instead of getting run.
+This could be confusing.
+.SH PERMISSIONS
+.PP
+thttpd is also picky about file permissions.
+It wants data files (HTML, images) to be world readable.
+Readable by the group that the thttpd process runs as is not enough - thttpd
+checks explicitly for the world-readable bit.
+This is so that no one ever gets surprised by a file that's not set
+world-readable and yet somehow is readable by the HTTP server and
+therefore the *whole* world.
+.PP
+The same logic applies to directories.
+As with the standard Unix "ls" program, thttpd will only let you
+look at the contents of a directory if its read bit is on; but
+as with data files, this must be the world-read bit, not just the
+group-read bit.
+.PP
+thttpd also wants the execute bit to be *off* for data files.
+A file that is marked executable but doesn't match the CGI pattern
+might be a script or program that got accidentally left in the
+wrong directory.
+Allowing people to fetch the contents of the file might be a security breach,
+so this is prohibited.
+Of course if an executable file *does* match the CGI pattern, then it
+just gets run as a CGI.
+.PP
+In summary, data files should be mode 644 (rw-r--r--),
+directories should be 755 (rwxr-xr-x) if you want to allow indexing and
+711 (rwx--x--x) to disallow it, and CGI programs should be mode
+755 (rwxr-xr-x) or 711 (rwx--x--x).
+.SH LOGS
+.PP
+thttpd does all of its logging via syslog(3).
+The facility it uses is configurable.
+Aside from error messages, there are only a few log entry types of interest,
+all fairly similar to CERN Common Log Format:
+.nf
+ Aug 6 15:40:34 acme thttpd[583]: 165.113.207.103 - - "GET /file" 200 357
+ Aug 6 15:40:43 acme thttpd[583]: 165.113.207.103 - - "HEAD /file" 200 0
+ Aug 6 15:41:16 acme thttpd[583]: referrer http://www.acme.com/ -> /dir
+ Aug 6 15:41:16 acme thttpd[583]: user-agent Mozilla/1.1N
+.fi
+The package includes a script for translating these log entries info
+CERN-compatible files.
+Note that thttpd does not translate numeric IP addresses into domain names.
+This is both to save time and as a minor security measure (the numeric
+address is harder to spoof).
+.PP
+Relevant config.h option: LOG_FACILITY.
+.PP
+If you'd rather log directly to a file, you can use the -l command-line
+flag. But note that error messages still go to syslog.
+.SH SIGNALS
+.PP
+thttpd handles a couple of signals, which you can send via the
+standard Unix kill(1) command:
+.TP
+.B INT,TERM
+These signals tell thttpd to shut down immediately.
+Any requests in progress get aborted.
+.TP
+.B USR1
+This signal tells thttpd to shut down as soon as it's done servicing
+all current requests.
+In addition, the network socket it uses to accept new connections gets
+closed immediately, which means a fresh thttpd can be started up
+immediately.
+.TP
+.B USR2
+This signal tells thttpd to generate the statistics syslog messages
+immediately, instead of waiting for the regular hourly update.
+.TP
+.B HUP
+This signal tells thttpd to close and re-open its (non-syslog) log file,
+for instance if you rotated the logs and want it to start using the
+new one.
+This is a little tricky to set up correctly, for instance if you are using
+chroot() then the log file must be within the chroot tree, but it's
+definitely doable.
+.SH "SEE ALSO"
+redirect(8), ssi(8), makeweb(1), htpasswd(1), syslogtocern(8), weblog_parse(1), http_get(1)
+.SH THANKS
+.PP
+Many thanks to contributors, reviewers, testers:
+John LoVerso, Jordan Hayes, Chris Torek, Jim Thompson, Barton Schaffer,
+Geoff Adams, Dan Kegel, John Hascall, Bennett Todd, KIKUCHI Takahiro,
+Catalin Ionescu.
+Special thanks to Craig Leres for substantial debugging and development,
+and for not complaining about my coding style very much.
+.SH AUTHOR
+Copyright © 1995,1998,1999,2000 by Jef Poskanzer <jef@mail.acme.com>.
+All rights reserved.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
--- /dev/null
+/* thttpd.c - tiny/turbo/throttling HTTP server
+**
+** Copyright © 1995,1998,1999,2000,2001,2015 by
+** Jef Poskanzer <jef@mail.acme.com>. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+
+#include "config.h"
+#include "version.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <pwd.h>
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#include <unistd.h>
+
+#include "fdwatch.h"
+#include "libhttpd.h"
+#include "mmc.h"
+#include "timers.h"
+#include "match.h"
+
+#ifndef SHUT_WR
+#define SHUT_WR 1
+#endif
+
+#ifndef HAVE_INT64T
+typedef long long int64_t;
+#endif
+
+
+static char* argv0;
+static int debug;
+static unsigned short port;
+static char* dir;
+static char* data_dir;
+static int do_chroot, no_log, no_symlink_check, do_vhost, do_global_passwd;
+static char* cgi_pattern;
+static int cgi_limit;
+static char* url_pattern;
+static int no_empty_referrers;
+static char* local_pattern;
+static char* logfile;
+static char* throttlefile;
+static char* hostname;
+static char* pidfile;
+static char* user;
+static char* charset;
+static char* p3p;
+static int max_age;
+
+
+typedef struct {
+ char* pattern;
+ long max_limit, min_limit;
+ long rate;
+ off_t bytes_since_avg;
+ int num_sending;
+ } throttletab;
+static throttletab* throttles;
+static int numthrottles, maxthrottles;
+
+#define THROTTLE_NOLIMIT -1
+
+
+typedef struct {
+ int conn_state;
+ int next_free_connect;
+ httpd_conn* hc;
+ int tnums[MAXTHROTTLENUMS]; /* throttle indexes */
+ int numtnums;
+ long max_limit, min_limit;
+ time_t started_at, active_at;
+ Timer* wakeup_timer;
+ Timer* linger_timer;
+ long wouldblock_delay;
+ off_t bytes;
+ off_t end_byte_index;
+ off_t next_byte_index;
+ } connecttab;
+static connecttab* connects;
+static int num_connects, max_connects, first_free_connect;
+static int httpd_conn_count;
+
+/* The connection states. */
+#define CNST_FREE 0
+#define CNST_READING 1
+#define CNST_SENDING 2
+#define CNST_PAUSING 3
+#define CNST_LINGERING 4
+
+
+static httpd_server* hs = (httpd_server*) 0;
+int terminate = 0;
+time_t start_time, stats_time;
+long stats_connections;
+off_t stats_bytes;
+int stats_simultaneous;
+
+static volatile int got_hup, got_usr1, watchdog_flag;
+
+
+/* Forwards. */
+static void parse_args( int argc, char** argv );
+static void usage( void );
+static void read_config( char* filename );
+static void value_required( char* name, char* value );
+static void no_value_required( char* name, char* value );
+static char* e_strdup( char* oldstr );
+static void lookup_hostname( httpd_sockaddr* sa4P, size_t sa4_len, int* gotv4P, httpd_sockaddr* sa6P, size_t sa6_len, int* gotv6P );
+static void read_throttlefile( char* tf );
+static void shut_down( void );
+static int handle_newconnect( struct timeval* tvP, int listen_fd );
+static void handle_read( connecttab* c, struct timeval* tvP );
+static void handle_send( connecttab* c, struct timeval* tvP );
+static void handle_linger( connecttab* c, struct timeval* tvP );
+static int check_throttles( connecttab* c );
+static void clear_throttles( connecttab* c, struct timeval* tvP );
+static void update_throttles( ClientData client_data, struct timeval* nowP );
+static void finish_connection( connecttab* c, struct timeval* tvP );
+static void clear_connection( connecttab* c, struct timeval* tvP );
+static void really_clear_connection( connecttab* c, struct timeval* tvP );
+static void idle( ClientData client_data, struct timeval* nowP );
+static void wakeup_connection( ClientData client_data, struct timeval* nowP );
+static void linger_clear_connection( ClientData client_data, struct timeval* nowP );
+static void occasional( ClientData client_data, struct timeval* nowP );
+#ifdef STATS_TIME
+static void show_stats( ClientData client_data, struct timeval* nowP );
+#endif /* STATS_TIME */
+static void logstats( struct timeval* nowP );
+static void thttpd_logstats( long secs );
+
+
+/* SIGTERM and SIGINT say to exit immediately. */
+static void
+handle_term( int sig )
+ {
+ /* Don't need to set up the handler again, since it's a one-shot. */
+
+ shut_down();
+ syslog( LOG_NOTICE, "exiting due to signal %d", sig );
+ closelog();
+ exit( 1 );
+ }
+
+
+/* SIGCHLD - a chile process exitted, so we need to reap the zombie */
+static void
+handle_chld( int sig )
+ {
+ const int oerrno = errno;
+ pid_t pid;
+ int status;
+
+#ifndef HAVE_SIGSET
+ /* Set up handler again. */
+ (void) signal( SIGCHLD, handle_chld );
+#endif /* ! HAVE_SIGSET */
+
+ /* Reap defunct children until there aren't any more. */
+ for (;;)
+ {
+#ifdef HAVE_WAITPID
+ pid = waitpid( (pid_t) -1, &status, WNOHANG );
+#else /* HAVE_WAITPID */
+ pid = wait3( &status, WNOHANG, (struct rusage*) 0 );
+#endif /* HAVE_WAITPID */
+ if ( (int) pid == 0 ) /* none left */
+ break;
+ if ( (int) pid < 0 )
+ {
+ if ( errno == EINTR || errno == EAGAIN )
+ continue;
+ /* ECHILD shouldn't happen with the WNOHANG option,
+ ** but with some kernels it does anyway. Ignore it.
+ */
+ if ( errno != ECHILD )
+ syslog( LOG_ERR, "child wait - %m" );
+ break;
+ }
+ /* Decrement the CGI count. Note that this is not accurate, since
+ ** each CGI can involve two or even three child processes.
+ ** Decrementing for each child means that when there is heavy CGI
+ ** activity, the count will be lower than it should be, and therefore
+ ** more CGIs will be allowed than should be.
+ */
+ if ( hs != (httpd_server*) 0 )
+ {
+ --hs->cgi_count;
+ if ( hs->cgi_count < 0 )
+ hs->cgi_count = 0;
+ }
+ }
+
+ /* Restore previous errno. */
+ errno = oerrno;
+ }
+
+
+/* SIGHUP says to re-open the log file. */
+static void
+handle_hup( int sig )
+ {
+ const int oerrno = errno;
+
+#ifndef HAVE_SIGSET
+ /* Set up handler again. */
+ (void) signal( SIGHUP, handle_hup );
+#endif /* ! HAVE_SIGSET */
+
+ /* Just set a flag that we got the signal. */
+ got_hup = 1;
+
+ /* Restore previous errno. */
+ errno = oerrno;
+ }
+
+
+/* SIGUSR1 says to exit as soon as all current connections are done. */
+static void
+handle_usr1( int sig )
+ {
+ /* Don't need to set up the handler again, since it's a one-shot. */
+
+ if ( num_connects == 0 )
+ {
+ /* If there are no active connections we want to exit immediately
+ ** here. Not only is it faster, but without any connections the
+ ** main loop won't wake up until the next new connection.
+ */
+ shut_down();
+ syslog( LOG_NOTICE, "exiting" );
+ closelog();
+ exit( 0 );
+ }
+
+ /* Otherwise, just set a flag that we got the signal. */
+ got_usr1 = 1;
+
+ /* Don't need to restore old errno, since we didn't do any syscalls. */
+ }
+
+
+/* SIGUSR2 says to generate the stats syslogs immediately. */
+static void
+handle_usr2( int sig )
+ {
+ const int oerrno = errno;
+
+#ifndef HAVE_SIGSET
+ /* Set up handler again. */
+ (void) signal( SIGUSR2, handle_usr2 );
+#endif /* ! HAVE_SIGSET */
+
+ logstats( (struct timeval*) 0 );
+
+ /* Restore previous errno. */
+ errno = oerrno;
+ }
+
+
+/* SIGALRM is used as a watchdog. */
+static void
+handle_alrm( int sig )
+ {
+ const int oerrno = errno;
+
+ /* If nothing has been happening */
+ if ( ! watchdog_flag )
+ {
+ /* Try changing dirs to someplace we can write. */
+ (void) chdir( "/tmp" );
+ /* Dump core. */
+ abort();
+ }
+ watchdog_flag = 0;
+
+#ifndef HAVE_SIGSET
+ /* Set up handler again. */
+ (void) signal( SIGALRM, handle_alrm );
+#endif /* ! HAVE_SIGSET */
+ /* Set up alarm again. */
+ (void) alarm( OCCASIONAL_TIME * 3 );
+
+ /* Restore previous errno. */
+ errno = oerrno;
+ }
+
+
+static void
+re_open_logfile( void )
+ {
+ FILE* logfp;
+
+ if ( no_log || hs == (httpd_server*) 0 )
+ return;
+
+ /* Re-open the log file. */
+ if ( logfile != (char*) 0 && strcmp( logfile, "-" ) != 0 )
+ {
+ syslog( LOG_NOTICE, "re-opening logfile" );
+ logfp = fopen( logfile, "a" );
+ if ( logfp == (FILE*) 0 )
+ {
+ syslog( LOG_CRIT, "re-opening %.80s - %m", logfile );
+ return;
+ }
+ (void) fcntl( fileno( logfp ), F_SETFD, 1 );
+ httpd_set_logfp( hs, logfp );
+ }
+ }
+
+
+int
+main( int argc, char** argv )
+ {
+ char* cp;
+ struct passwd* pwd;
+ uid_t uid = 32767;
+ gid_t gid = 32767;
+ char cwd[MAXPATHLEN+1];
+ FILE* logfp;
+ int num_ready;
+ int cnum;
+ connecttab* c;
+ httpd_conn* hc;
+ httpd_sockaddr sa4;
+ httpd_sockaddr sa6;
+ int gotv4, gotv6;
+ struct timeval tv;
+
+ argv0 = argv[0];
+
+ cp = strrchr( argv0, '/' );
+ if ( cp != (char*) 0 )
+ ++cp;
+ else
+ cp = argv0;
+ openlog( cp, LOG_NDELAY|LOG_PID, LOG_FACILITY );
+
+ /* Handle command-line arguments. */
+ parse_args( argc, argv );
+
+ /* Read zone info now, in case we chroot(). */
+ tzset();
+
+ /* Look up hostname now, in case we chroot(). */
+ lookup_hostname( &sa4, sizeof(sa4), &gotv4, &sa6, sizeof(sa6), &gotv6 );
+ if ( ! ( gotv4 || gotv6 ) )
+ {
+ syslog( LOG_ERR, "can't find any valid address" );
+ (void) fprintf( stderr, "%s: can't find any valid address\n", argv0 );
+ exit( 1 );
+ }
+
+ /* Throttle file. */
+ numthrottles = 0;
+ maxthrottles = 0;
+ throttles = (throttletab*) 0;
+ if ( throttlefile != (char*) 0 )
+ read_throttlefile( throttlefile );
+
+ /* If we're root and we're going to become another user, get the uid/gid
+ ** now.
+ */
+ if ( getuid() == 0 )
+ {
+ pwd = getpwnam( user );
+ if ( pwd == (struct passwd*) 0 )
+ {
+ syslog( LOG_CRIT, "unknown user - '%.80s'", user );
+ (void) fprintf( stderr, "%s: unknown user - '%s'\n", argv0, user );
+ exit( 1 );
+ }
+ uid = pwd->pw_uid;
+ gid = pwd->pw_gid;
+ }
+
+ /* Log file. */
+ if ( logfile != (char*) 0 )
+ {
+ if ( strcmp( logfile, "/dev/null" ) == 0 )
+ {
+ no_log = 1;
+ logfp = (FILE*) 0;
+ }
+ else if ( strcmp( logfile, "-" ) == 0 )
+ logfp = stdout;
+ else
+ {
+ logfp = fopen( logfile, "a" );
+ if ( logfp == (FILE*) 0 )
+ {
+ syslog( LOG_CRIT, "%.80s - %m", logfile );
+ perror( logfile );
+ exit( 1 );
+ }
+ if ( logfile[0] != '/' )
+ {
+ syslog( LOG_WARNING, "logfile is not an absolute path, you may not be able to re-open it" );
+ (void) fprintf( stderr, "%s: logfile is not an absolute path, you may not be able to re-open it\n", argv0 );
+ }
+ (void) fcntl( fileno( logfp ), F_SETFD, 1 );
+ if ( getuid() == 0 )
+ {
+ /* If we are root then we chown the log file to the user we'll
+ ** be switching to.
+ */
+ if ( fchown( fileno( logfp ), uid, gid ) < 0 )
+ {
+ syslog( LOG_WARNING, "fchown logfile - %m" );
+ perror( "fchown logfile" );
+ }
+ }
+ }
+ }
+ else
+ logfp = (FILE*) 0;
+
+ /* Switch directories if requested. */
+ if ( dir != (char*) 0 )
+ {
+ if ( chdir( dir ) < 0 )
+ {
+ syslog( LOG_CRIT, "chdir - %m" );
+ perror( "chdir" );
+ exit( 1 );
+ }
+ }
+#ifdef USE_USER_DIR
+ else if ( getuid() == 0 )
+ {
+ /* No explicit directory was specified, we're root, and the
+ ** USE_USER_DIR option is set - switch to the specified user's
+ ** home dir.
+ */
+ if ( chdir( pwd->pw_dir ) < 0 )
+ {
+ syslog( LOG_CRIT, "chdir - %m" );
+ perror( "chdir" );
+ exit( 1 );
+ }
+ }
+#endif /* USE_USER_DIR */
+
+ /* Get current directory. */
+ (void) getcwd( cwd, sizeof(cwd) - 1 );
+ if ( cwd[strlen( cwd ) - 1] != '/' )
+ (void) strcat( cwd, "/" );
+
+ if ( ! debug )
+ {
+ /* We're not going to use stdin stdout or stderr from here on, so close
+ ** them to save file descriptors.
+ */
+ (void) fclose( stdin );
+ if ( logfp != stdout )
+ (void) fclose( stdout );
+ (void) fclose( stderr );
+
+ /* Daemonize - make ourselves a subprocess. */
+#ifdef HAVE_DAEMON
+ if ( daemon( 1, 1 ) < 0 )
+ {
+ syslog( LOG_CRIT, "daemon - %m" );
+ exit( 1 );
+ }
+#else /* HAVE_DAEMON */
+ switch ( fork() )
+ {
+ case 0:
+ break;
+ case -1:
+ syslog( LOG_CRIT, "fork - %m" );
+ exit( 1 );
+ default:
+ exit( 0 );
+ }
+#ifdef HAVE_SETSID
+ (void) setsid();
+#endif /* HAVE_SETSID */
+#endif /* HAVE_DAEMON */
+ }
+ else
+ {
+ /* Even if we don't daemonize, we still want to disown our parent
+ ** process.
+ */
+#ifdef HAVE_SETSID
+ (void) setsid();
+#endif /* HAVE_SETSID */
+ }
+
+ if ( pidfile != (char*) 0 )
+ {
+ /* Write the PID file. */
+ FILE* pidfp = fopen( pidfile, "w" );
+ if ( pidfp == (FILE*) 0 )
+ {
+ syslog( LOG_CRIT, "%.80s - %m", pidfile );
+ exit( 1 );
+ }
+ (void) fprintf( pidfp, "%d\n", (int) getpid() );
+ (void) fclose( pidfp );
+ }
+
+ /* Initialize the fdwatch package. Have to do this before chroot,
+ ** if /dev/poll is used.
+ */
+ max_connects = fdwatch_get_nfiles();
+ if ( max_connects < 0 )
+ {
+ syslog( LOG_CRIT, "fdwatch initialization failure" );
+ exit( 1 );
+ }
+ max_connects -= SPARE_FDS;
+
+ /* Chroot if requested. */
+ if ( do_chroot )
+ {
+ if ( chroot( cwd ) < 0 )
+ {
+ syslog( LOG_CRIT, "chroot - %m" );
+ perror( "chroot" );
+ exit( 1 );
+ }
+ /* If we're logging and the logfile's pathname begins with the
+ ** chroot tree's pathname, then elide the chroot pathname so
+ ** that the logfile pathname still works from inside the chroot
+ ** tree.
+ */
+ if ( logfile != (char*) 0 && strcmp( logfile, "-" ) != 0 )
+ {
+ if ( strncmp( logfile, cwd, strlen( cwd ) ) == 0 )
+ {
+ (void) ol_strcpy( logfile, &logfile[strlen( cwd ) - 1] );
+ /* (We already guaranteed that cwd ends with a slash, so leaving
+ ** that slash in logfile makes it an absolute pathname within
+ ** the chroot tree.)
+ */
+ }
+ else
+ {
+ syslog( LOG_WARNING, "logfile is not within the chroot tree, you will not be able to re-open it" );
+ (void) fprintf( stderr, "%s: logfile is not within the chroot tree, you will not be able to re-open it\n", argv0 );
+ }
+ }
+ (void) strcpy( cwd, "/" );
+ /* Always chdir to / after a chroot. */
+ if ( chdir( cwd ) < 0 )
+ {
+ syslog( LOG_CRIT, "chroot chdir - %m" );
+ perror( "chroot chdir" );
+ exit( 1 );
+ }
+ }
+
+ /* Switch directories again if requested. */
+ if ( data_dir != (char*) 0 )
+ {
+ if ( chdir( data_dir ) < 0 )
+ {
+ syslog( LOG_CRIT, "data_dir chdir - %m" );
+ perror( "data_dir chdir" );
+ exit( 1 );
+ }
+ }
+
+ /* Set up to catch signals. */
+#ifdef HAVE_SIGSET
+ (void) sigset( SIGTERM, handle_term );
+ (void) sigset( SIGINT, handle_term );
+ (void) sigset( SIGCHLD, handle_chld );
+ (void) sigset( SIGPIPE, SIG_IGN ); /* get EPIPE instead */
+ (void) sigset( SIGHUP, handle_hup );
+ (void) sigset( SIGUSR1, handle_usr1 );
+ (void) sigset( SIGUSR2, handle_usr2 );
+ (void) sigset( SIGALRM, handle_alrm );
+#else /* HAVE_SIGSET */
+ (void) signal( SIGTERM, handle_term );
+ (void) signal( SIGINT, handle_term );
+ (void) signal( SIGCHLD, handle_chld );
+ (void) signal( SIGPIPE, SIG_IGN ); /* get EPIPE instead */
+ (void) signal( SIGHUP, handle_hup );
+ (void) signal( SIGUSR1, handle_usr1 );
+ (void) signal( SIGUSR2, handle_usr2 );
+ (void) signal( SIGALRM, handle_alrm );
+#endif /* HAVE_SIGSET */
+ got_hup = 0;
+ got_usr1 = 0;
+ watchdog_flag = 0;
+ (void) alarm( OCCASIONAL_TIME * 3 );
+
+ /* Initialize the timer package. */
+ tmr_init();
+
+ /* Initialize the HTTP layer. Got to do this before giving up root,
+ ** so that we can bind to a privileged port.
+ */
+ hs = httpd_initialize(
+ hostname,
+ gotv4 ? &sa4 : (httpd_sockaddr*) 0, gotv6 ? &sa6 : (httpd_sockaddr*) 0,
+ port, cgi_pattern, cgi_limit, charset, p3p, max_age, cwd, no_log, logfp,
+ no_symlink_check, do_vhost, do_global_passwd, url_pattern,
+ local_pattern, no_empty_referrers );
+ if ( hs == (httpd_server*) 0 )
+ exit( 1 );
+
+ /* Set up the occasional timer. */
+ if ( tmr_create( (struct timeval*) 0, occasional, JunkClientData, OCCASIONAL_TIME * 1000L, 1 ) == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(occasional) failed" );
+ exit( 1 );
+ }
+ /* Set up the idle timer. */
+ if ( tmr_create( (struct timeval*) 0, idle, JunkClientData, 5 * 1000L, 1 ) == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(idle) failed" );
+ exit( 1 );
+ }
+ if ( numthrottles > 0 )
+ {
+ /* Set up the throttles timer. */
+ if ( tmr_create( (struct timeval*) 0, update_throttles, JunkClientData, THROTTLE_TIME * 1000L, 1 ) == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(update_throttles) failed" );
+ exit( 1 );
+ }
+ }
+#ifdef STATS_TIME
+ /* Set up the stats timer. */
+ if ( tmr_create( (struct timeval*) 0, show_stats, JunkClientData, STATS_TIME * 1000L, 1 ) == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(show_stats) failed" );
+ exit( 1 );
+ }
+#endif /* STATS_TIME */
+ start_time = stats_time = time( (time_t*) 0 );
+ stats_connections = 0;
+ stats_bytes = 0;
+ stats_simultaneous = 0;
+
+ /* If we're root, try to become someone else. */
+ if ( getuid() == 0 )
+ {
+ /* Set aux groups to null. */
+ if ( setgroups( 0, (const gid_t*) 0 ) < 0 )
+ {
+ syslog( LOG_CRIT, "setgroups - %m" );
+ exit( 1 );
+ }
+ /* Set primary group. */
+ if ( setgid( gid ) < 0 )
+ {
+ syslog( LOG_CRIT, "setgid - %m" );
+ exit( 1 );
+ }
+ /* Try setting aux groups correctly - not critical if this fails. */
+ if ( initgroups( user, gid ) < 0 )
+ syslog( LOG_WARNING, "initgroups - %m" );
+#ifdef HAVE_SETLOGIN
+ /* Set login name. */
+ (void) setlogin( user );
+#endif /* HAVE_SETLOGIN */
+ /* Set uid. */
+ if ( setuid( uid ) < 0 )
+ {
+ syslog( LOG_CRIT, "setuid - %m" );
+ exit( 1 );
+ }
+ /* Check for unnecessary security exposure. */
+ if ( ! do_chroot )
+ syslog(
+ LOG_WARNING,
+ "started as root without requesting chroot(), warning only" );
+ }
+
+ /* Initialize our connections table. */
+ connects = NEW( connecttab, max_connects );
+ if ( connects == (connecttab*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory allocating a connecttab" );
+ exit( 1 );
+ }
+ for ( cnum = 0; cnum < max_connects; ++cnum )
+ {
+ connects[cnum].conn_state = CNST_FREE;
+ connects[cnum].next_free_connect = cnum + 1;
+ connects[cnum].hc = (httpd_conn*) 0;
+ }
+ connects[max_connects - 1].next_free_connect = -1; /* end of link list */
+ first_free_connect = 0;
+ num_connects = 0;
+ httpd_conn_count = 0;
+
+ if ( hs != (httpd_server*) 0 )
+ {
+ if ( hs->listen4_fd != -1 )
+ fdwatch_add_fd( hs->listen4_fd, (void*) 0, FDW_READ );
+ if ( hs->listen6_fd != -1 )
+ fdwatch_add_fd( hs->listen6_fd, (void*) 0, FDW_READ );
+ }
+
+ /* Main loop. */
+ (void) gettimeofday( &tv, (struct timezone*) 0 );
+ while ( ( ! terminate ) || num_connects > 0 )
+ {
+ /* Do we need to re-open the log file? */
+ if ( got_hup )
+ {
+ re_open_logfile();
+ got_hup = 0;
+ }
+
+ /* Do the fd watch. */
+ num_ready = fdwatch( tmr_mstimeout( &tv ) );
+ if ( num_ready < 0 )
+ {
+ if ( errno == EINTR || errno == EAGAIN )
+ continue; /* try again */
+ syslog( LOG_ERR, "fdwatch - %m" );
+ exit( 1 );
+ }
+ (void) gettimeofday( &tv, (struct timezone*) 0 );
+
+ if ( num_ready == 0 )
+ {
+ /* No fd's are ready - run the timers. */
+ tmr_run( &tv );
+ continue;
+ }
+
+ /* Is it a new connection? */
+ if ( hs != (httpd_server*) 0 && hs->listen6_fd != -1 &&
+ fdwatch_check_fd( hs->listen6_fd ) )
+ {
+ if ( handle_newconnect( &tv, hs->listen6_fd ) )
+ /* Go around the loop and do another fdwatch, rather than
+ ** dropping through and processing existing connections.
+ ** New connections always get priority.
+ */
+ continue;
+ }
+ if ( hs != (httpd_server*) 0 && hs->listen4_fd != -1 &&
+ fdwatch_check_fd( hs->listen4_fd ) )
+ {
+ if ( handle_newconnect( &tv, hs->listen4_fd ) )
+ /* Go around the loop and do another fdwatch, rather than
+ ** dropping through and processing existing connections.
+ ** New connections always get priority.
+ */
+ continue;
+ }
+
+ /* Find the connections that need servicing. */
+ while ( ( c = (connecttab*) fdwatch_get_next_client_data() ) != (connecttab*) -1 )
+ {
+ if ( c == (connecttab*) 0 )
+ continue;
+ hc = c->hc;
+ if ( ! fdwatch_check_fd( hc->conn_fd ) )
+ /* Something went wrong. */
+ clear_connection( c, &tv );
+ else
+ switch ( c->conn_state )
+ {
+ case CNST_READING: handle_read( c, &tv ); break;
+ case CNST_SENDING: handle_send( c, &tv ); break;
+ case CNST_LINGERING: handle_linger( c, &tv ); break;
+ }
+ }
+ tmr_run( &tv );
+
+ if ( got_usr1 && ! terminate )
+ {
+ terminate = 1;
+ if ( hs != (httpd_server*) 0 )
+ {
+ if ( hs->listen4_fd != -1 )
+ fdwatch_del_fd( hs->listen4_fd );
+ if ( hs->listen6_fd != -1 )
+ fdwatch_del_fd( hs->listen6_fd );
+ httpd_unlisten( hs );
+ }
+ }
+ }
+
+ /* The main loop terminated. */
+ shut_down();
+ syslog( LOG_NOTICE, "exiting" );
+ closelog();
+ exit( 0 );
+ }
+
+
+static void
+parse_args( int argc, char** argv )
+ {
+ int argn;
+
+ debug = 0;
+ port = DEFAULT_PORT;
+ dir = (char*) 0;
+ data_dir = (char*) 0;
+#ifdef ALWAYS_CHROOT
+ do_chroot = 1;
+#else /* ALWAYS_CHROOT */
+ do_chroot = 0;
+#endif /* ALWAYS_CHROOT */
+ no_log = 0;
+ no_symlink_check = do_chroot;
+#ifdef ALWAYS_VHOST
+ do_vhost = 1;
+#else /* ALWAYS_VHOST */
+ do_vhost = 0;
+#endif /* ALWAYS_VHOST */
+#ifdef ALWAYS_GLOBAL_PASSWD
+ do_global_passwd = 1;
+#else /* ALWAYS_GLOBAL_PASSWD */
+ do_global_passwd = 0;
+#endif /* ALWAYS_GLOBAL_PASSWD */
+#ifdef CGI_PATTERN
+ cgi_pattern = CGI_PATTERN;
+#else /* CGI_PATTERN */
+ cgi_pattern = (char*) 0;
+#endif /* CGI_PATTERN */
+#ifdef CGI_LIMIT
+ cgi_limit = CGI_LIMIT;
+#else /* CGI_LIMIT */
+ cgi_limit = 0;
+#endif /* CGI_LIMIT */
+ url_pattern = (char*) 0;
+ no_empty_referrers = 0;
+ local_pattern = (char*) 0;
+ throttlefile = (char*) 0;
+ hostname = (char*) 0;
+ logfile = (char*) 0;
+ pidfile = (char*) 0;
+ user = DEFAULT_USER;
+ charset = DEFAULT_CHARSET;
+ p3p = "";
+ max_age = -1;
+ argn = 1;
+ while ( argn < argc && argv[argn][0] == '-' )
+ {
+ if ( strcmp( argv[argn], "-V" ) == 0 )
+ {
+ (void) printf( "%s\n", SERVER_SOFTWARE );
+ exit( 0 );
+ }
+ else if ( strcmp( argv[argn], "-C" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ read_config( argv[argn] );
+ }
+ else if ( strcmp( argv[argn], "-p" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ port = (unsigned short) atoi( argv[argn] );
+ }
+ else if ( strcmp( argv[argn], "-d" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ dir = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-r" ) == 0 )
+ {
+ do_chroot = 1;
+ no_symlink_check = 1;
+ }
+ else if ( strcmp( argv[argn], "-nor" ) == 0 )
+ {
+ do_chroot = 0;
+ no_symlink_check = 0;
+ }
+ else if ( strcmp( argv[argn], "-dd" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ data_dir = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-s" ) == 0 )
+ no_symlink_check = 0;
+ else if ( strcmp( argv[argn], "-nos" ) == 0 )
+ no_symlink_check = 1;
+ else if ( strcmp( argv[argn], "-u" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ user = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-c" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ cgi_pattern = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-t" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ throttlefile = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-h" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ hostname = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-l" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ logfile = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-v" ) == 0 )
+ do_vhost = 1;
+ else if ( strcmp( argv[argn], "-nov" ) == 0 )
+ do_vhost = 0;
+ else if ( strcmp( argv[argn], "-g" ) == 0 )
+ do_global_passwd = 1;
+ else if ( strcmp( argv[argn], "-nog" ) == 0 )
+ do_global_passwd = 0;
+ else if ( strcmp( argv[argn], "-i" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ pidfile = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-T" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ charset = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-P" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ p3p = argv[argn];
+ }
+ else if ( strcmp( argv[argn], "-M" ) == 0 && argn + 1 < argc )
+ {
+ ++argn;
+ max_age = atoi( argv[argn] );
+ }
+ else if ( strcmp( argv[argn], "-D" ) == 0 )
+ debug = 1;
+ else
+ usage();
+ ++argn;
+ }
+ if ( argn != argc )
+ usage();
+ }
+
+
+static void
+usage( void )
+ {
+ (void) fprintf( stderr,
+"usage: %s [-C configfile] [-p port] [-d dir] [-r|-nor] [-dd data_dir] [-s|-nos] [-v|-nov] [-g|-nog] [-u user] [-c cgipat] [-t throttles] [-h host] [-l logfile] [-i pidfile] [-T charset] [-P P3P] [-M maxage] [-V] [-D]\n",
+ argv0 );
+ exit( 1 );
+ }
+
+
+static void
+read_config( char* filename )
+ {
+ FILE* fp;
+ char line[10000];
+ char* cp;
+ char* cp2;
+ char* name;
+ char* value;
+
+ fp = fopen( filename, "r" );
+ if ( fp == (FILE*) 0 )
+ {
+ perror( filename );
+ exit( 1 );
+ }
+
+ while ( fgets( line, sizeof(line), fp ) != (char*) 0 )
+ {
+ /* Trim comments. */
+ if ( ( cp = strchr( line, '#' ) ) != (char*) 0 )
+ *cp = '\0';
+
+ /* Skip leading whitespace. */
+ cp = line;
+ cp += strspn( cp, " \t\n\r" );
+
+ /* Split line into words. */
+ while ( *cp != '\0' )
+ {
+ /* Find next whitespace. */
+ cp2 = cp + strcspn( cp, " \t\n\r" );
+ /* Insert EOS and advance next-word pointer. */
+ while ( *cp2 == ' ' || *cp2 == '\t' || *cp2 == '\n' || *cp2 == '\r' )
+ *cp2++ = '\0';
+ /* Split into name and value. */
+ name = cp;
+ value = strchr( name, '=' );
+ if ( value != (char*) 0 )
+ *value++ = '\0';
+ /* Interpret. */
+ if ( strcasecmp( name, "debug" ) == 0 )
+ {
+ no_value_required( name, value );
+ debug = 1;
+ }
+ else if ( strcasecmp( name, "port" ) == 0 )
+ {
+ value_required( name, value );
+ port = (unsigned short) atoi( value );
+ }
+ else if ( strcasecmp( name, "dir" ) == 0 )
+ {
+ value_required( name, value );
+ dir = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "chroot" ) == 0 )
+ {
+ no_value_required( name, value );
+ do_chroot = 1;
+ no_symlink_check = 1;
+ }
+ else if ( strcasecmp( name, "nochroot" ) == 0 )
+ {
+ no_value_required( name, value );
+ do_chroot = 0;
+ no_symlink_check = 0;
+ }
+ else if ( strcasecmp( name, "data_dir" ) == 0 )
+ {
+ value_required( name, value );
+ data_dir = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "nosymlinkcheck" ) == 0 )
+ {
+ no_value_required( name, value );
+ no_symlink_check = 1;
+ }
+ else if ( strcasecmp( name, "symlinkcheck" ) == 0 )
+ {
+ no_value_required( name, value );
+ no_symlink_check = 0;
+ }
+ else if ( strcasecmp( name, "user" ) == 0 )
+ {
+ value_required( name, value );
+ user = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "cgipat" ) == 0 )
+ {
+ value_required( name, value );
+ cgi_pattern = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "cgilimit" ) == 0 )
+ {
+ value_required( name, value );
+ cgi_limit = atoi( value );
+ }
+ else if ( strcasecmp( name, "urlpat" ) == 0 )
+ {
+ value_required( name, value );
+ url_pattern = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "noemptyreferers" ) == 0 ||
+ strcasecmp( name, "noemptyreferrers" ) == 0 )
+ {
+ no_value_required( name, value );
+ no_empty_referrers = 1;
+ }
+ else if ( strcasecmp( name, "localpat" ) == 0 )
+ {
+ value_required( name, value );
+ local_pattern = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "throttles" ) == 0 )
+ {
+ value_required( name, value );
+ throttlefile = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "host" ) == 0 )
+ {
+ value_required( name, value );
+ hostname = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "logfile" ) == 0 )
+ {
+ value_required( name, value );
+ logfile = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "vhost" ) == 0 )
+ {
+ no_value_required( name, value );
+ do_vhost = 1;
+ }
+ else if ( strcasecmp( name, "novhost" ) == 0 )
+ {
+ no_value_required( name, value );
+ do_vhost = 0;
+ }
+ else if ( strcasecmp( name, "globalpasswd" ) == 0 )
+ {
+ no_value_required( name, value );
+ do_global_passwd = 1;
+ }
+ else if ( strcasecmp( name, "noglobalpasswd" ) == 0 )
+ {
+ no_value_required( name, value );
+ do_global_passwd = 0;
+ }
+ else if ( strcasecmp( name, "pidfile" ) == 0 )
+ {
+ value_required( name, value );
+ pidfile = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "charset" ) == 0 )
+ {
+ value_required( name, value );
+ charset = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "p3p" ) == 0 )
+ {
+ value_required( name, value );
+ p3p = e_strdup( value );
+ }
+ else if ( strcasecmp( name, "max_age" ) == 0 )
+ {
+ value_required( name, value );
+ max_age = atoi( value );
+ }
+ else
+ {
+ (void) fprintf(
+ stderr, "%s: unknown config option '%s'\n", argv0, name );
+ exit( 1 );
+ }
+
+ /* Advance to next word. */
+ cp = cp2;
+ cp += strspn( cp, " \t\n\r" );
+ }
+ }
+
+ (void) fclose( fp );
+ }
+
+
+static void
+value_required( char* name, char* value )
+ {
+ if ( value == (char*) 0 )
+ {
+ (void) fprintf(
+ stderr, "%s: value required for %s option\n", argv0, name );
+ exit( 1 );
+ }
+ }
+
+
+static void
+no_value_required( char* name, char* value )
+ {
+ if ( value != (char*) 0 )
+ {
+ (void) fprintf(
+ stderr, "%s: no value required for %s option\n",
+ argv0, name );
+ exit( 1 );
+ }
+ }
+
+
+static char*
+e_strdup( char* oldstr )
+ {
+ char* newstr;
+
+ newstr = strdup( oldstr );
+ if ( newstr == (char*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory copying a string" );
+ (void) fprintf( stderr, "%s: out of memory copying a string\n", argv0 );
+ exit( 1 );
+ }
+ return newstr;
+ }
+
+
+static void
+lookup_hostname( httpd_sockaddr* sa4P, size_t sa4_len, int* gotv4P, httpd_sockaddr* sa6P, size_t sa6_len, int* gotv6P )
+ {
+#ifdef USE_IPV6
+
+ struct addrinfo hints;
+ char portstr[10];
+ int gaierr;
+ struct addrinfo* ai;
+ struct addrinfo* ai2;
+ struct addrinfo* aiv6;
+ struct addrinfo* aiv4;
+
+ (void) memset( &hints, 0, sizeof(hints) );
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_socktype = SOCK_STREAM;
+ (void) snprintf( portstr, sizeof(portstr), "%d", (int) port );
+ if ( (gaierr = getaddrinfo( hostname, portstr, &hints, &ai )) != 0 )
+ {
+ syslog(
+ LOG_CRIT, "getaddrinfo %.80s - %.80s",
+ hostname, gai_strerror( gaierr ) );
+ (void) fprintf(
+ stderr, "%s: getaddrinfo %s - %s\n",
+ argv0, hostname, gai_strerror( gaierr ) );
+ exit( 1 );
+ }
+
+ /* Find the first IPv6 and IPv4 entries. */
+ aiv6 = (struct addrinfo*) 0;
+ aiv4 = (struct addrinfo*) 0;
+ for ( ai2 = ai; ai2 != (struct addrinfo*) 0; ai2 = ai2->ai_next )
+ {
+ switch ( ai2->ai_family )
+ {
+ case AF_INET6:
+ if ( aiv6 == (struct addrinfo*) 0 )
+ aiv6 = ai2;
+ break;
+ case AF_INET:
+ if ( aiv4 == (struct addrinfo*) 0 )
+ aiv4 = ai2;
+ break;
+ }
+ }
+
+ if ( aiv6 == (struct addrinfo*) 0 )
+ *gotv6P = 0;
+ else
+ {
+ if ( sa6_len < aiv6->ai_addrlen )
+ {
+ syslog(
+ LOG_CRIT, "%.80s - sockaddr too small (%lu < %lu)",
+ hostname, (unsigned long) sa6_len,
+ (unsigned long) aiv6->ai_addrlen );
+ exit( 1 );
+ }
+ (void) memset( sa6P, 0, sa6_len );
+ (void) memmove( sa6P, aiv6->ai_addr, aiv6->ai_addrlen );
+ *gotv6P = 1;
+ }
+
+ if ( aiv4 == (struct addrinfo*) 0 )
+ *gotv4P = 0;
+ else
+ {
+ if ( sa4_len < aiv4->ai_addrlen )
+ {
+ syslog(
+ LOG_CRIT, "%.80s - sockaddr too small (%lu < %lu)",
+ hostname, (unsigned long) sa4_len,
+ (unsigned long) aiv4->ai_addrlen );
+ exit( 1 );
+ }
+ (void) memset( sa4P, 0, sa4_len );
+ (void) memmove( sa4P, aiv4->ai_addr, aiv4->ai_addrlen );
+ *gotv4P = 1;
+ }
+
+ freeaddrinfo( ai );
+
+#else /* USE_IPV6 */
+
+ struct hostent* he;
+
+ *gotv6P = 0;
+
+ (void) memset( sa4P, 0, sa4_len );
+ sa4P->sa.sa_family = AF_INET;
+ if ( hostname == (char*) 0 )
+ sa4P->sa_in.sin_addr.s_addr = htonl( INADDR_ANY );
+ else
+ {
+ sa4P->sa_in.sin_addr.s_addr = inet_addr( hostname );
+ if ( (int) sa4P->sa_in.sin_addr.s_addr == -1 )
+ {
+ he = gethostbyname( hostname );
+ if ( he == (struct hostent*) 0 )
+ {
+#ifdef HAVE_HSTRERROR
+ syslog(
+ LOG_CRIT, "gethostbyname %.80s - %.80s",
+ hostname, hstrerror( h_errno ) );
+ (void) fprintf(
+ stderr, "%s: gethostbyname %s - %s\n",
+ argv0, hostname, hstrerror( h_errno ) );
+#else /* HAVE_HSTRERROR */
+ syslog( LOG_CRIT, "gethostbyname %.80s failed", hostname );
+ (void) fprintf(
+ stderr, "%s: gethostbyname %s failed\n", argv0, hostname );
+#endif /* HAVE_HSTRERROR */
+ exit( 1 );
+ }
+ if ( he->h_addrtype != AF_INET )
+ {
+ syslog( LOG_CRIT, "%.80s - non-IP network address", hostname );
+ (void) fprintf(
+ stderr, "%s: %s - non-IP network address\n",
+ argv0, hostname );
+ exit( 1 );
+ }
+ (void) memmove(
+ &sa4P->sa_in.sin_addr.s_addr, he->h_addr, he->h_length );
+ }
+ }
+ sa4P->sa_in.sin_port = htons( port );
+ *gotv4P = 1;
+
+#endif /* USE_IPV6 */
+ }
+
+
+static void
+read_throttlefile( char* tf )
+ {
+ FILE* fp;
+ char buf[5000];
+ char* cp;
+ int len;
+ char pattern[5000];
+ long max_limit, min_limit;
+ struct timeval tv;
+
+ fp = fopen( tf, "r" );
+ if ( fp == (FILE*) 0 )
+ {
+ syslog( LOG_CRIT, "%.80s - %m", tf );
+ perror( tf );
+ exit( 1 );
+ }
+
+ (void) gettimeofday( &tv, (struct timezone*) 0 );
+
+ while ( fgets( buf, sizeof(buf), fp ) != (char*) 0 )
+ {
+ /* Nuke comments. */
+ cp = strchr( buf, '#' );
+ if ( cp != (char*) 0 )
+ *cp = '\0';
+
+ /* Nuke trailing whitespace. */
+ len = strlen( buf );
+ while ( len > 0 &&
+ ( buf[len-1] == ' ' || buf[len-1] == '\t' ||
+ buf[len-1] == '\n' || buf[len-1] == '\r' ) )
+ buf[--len] = '\0';
+
+ /* Ignore empty lines. */
+ if ( len == 0 )
+ continue;
+
+ /* Parse line. */
+ if ( sscanf( buf, " %4900[^ \t] %ld-%ld", pattern, &min_limit, &max_limit ) == 3 )
+ {}
+ else if ( sscanf( buf, " %4900[^ \t] %ld", pattern, &max_limit ) == 2 )
+ min_limit = 0;
+ else
+ {
+ syslog( LOG_CRIT,
+ "unparsable line in %.80s - %.80s", tf, buf );
+ (void) fprintf( stderr,
+ "%s: unparsable line in %.80s - %.80s\n",
+ argv0, tf, buf );
+ continue;
+ }
+
+ /* Nuke any leading slashes in pattern. */
+ if ( pattern[0] == '/' )
+ (void) ol_strcpy( pattern, &pattern[1] );
+ while ( ( cp = strstr( pattern, "|/" ) ) != (char*) 0 )
+ (void) ol_strcpy( cp + 1, cp + 2 );
+
+ /* Check for room in throttles. */
+ if ( numthrottles >= maxthrottles )
+ {
+ if ( maxthrottles == 0 )
+ {
+ maxthrottles = 100; /* arbitrary */
+ throttles = NEW( throttletab, maxthrottles );
+ }
+ else
+ {
+ maxthrottles *= 2;
+ throttles = RENEW( throttles, throttletab, maxthrottles );
+ }
+ if ( throttles == (throttletab*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory allocating a throttletab" );
+ (void) fprintf(
+ stderr, "%s: out of memory allocating a throttletab\n",
+ argv0 );
+ exit( 1 );
+ }
+ }
+
+ /* Add to table. */
+ throttles[numthrottles].pattern = e_strdup( pattern );
+ throttles[numthrottles].max_limit = max_limit;
+ throttles[numthrottles].min_limit = min_limit;
+ throttles[numthrottles].rate = 0;
+ throttles[numthrottles].bytes_since_avg = 0;
+ throttles[numthrottles].num_sending = 0;
+
+ ++numthrottles;
+ }
+ (void) fclose( fp );
+ }
+
+
+static void
+shut_down( void )
+ {
+ int cnum;
+ struct timeval tv;
+
+ (void) gettimeofday( &tv, (struct timezone*) 0 );
+ logstats( &tv );
+ for ( cnum = 0; cnum < max_connects; ++cnum )
+ {
+ if ( connects[cnum].conn_state != CNST_FREE )
+ httpd_close_conn( connects[cnum].hc, &tv );
+ if ( connects[cnum].hc != (httpd_conn*) 0 )
+ {
+ httpd_destroy_conn( connects[cnum].hc );
+ free( (void*) connects[cnum].hc );
+ --httpd_conn_count;
+ connects[cnum].hc = (httpd_conn*) 0;
+ }
+ }
+ if ( hs != (httpd_server*) 0 )
+ {
+ httpd_server* ths = hs;
+ hs = (httpd_server*) 0;
+ if ( ths->listen4_fd != -1 )
+ fdwatch_del_fd( ths->listen4_fd );
+ if ( ths->listen6_fd != -1 )
+ fdwatch_del_fd( ths->listen6_fd );
+ httpd_terminate( ths );
+ }
+ mmc_term();
+ tmr_term();
+ free( (void*) connects );
+ if ( throttles != (throttletab*) 0 )
+ free( (void*) throttles );
+ }
+
+
+static int
+handle_newconnect( struct timeval* tvP, int listen_fd )
+ {
+ connecttab* c;
+ ClientData client_data;
+
+ /* This loops until the accept() fails, trying to start new
+ ** connections as fast as possible so we don't overrun the
+ ** listen queue.
+ */
+ for (;;)
+ {
+ /* Is there room in the connection table? */
+ if ( num_connects >= max_connects )
+ {
+ /* Out of connection slots. Run the timers, then the
+ ** existing connections, and maybe we'll free up a slot
+ ** by the time we get back here.
+ */
+ syslog( LOG_WARNING, "too many connections!" );
+ tmr_run( tvP );
+ return 0;
+ }
+ /* Get the first free connection entry off the free list. */
+ if ( first_free_connect == -1 || connects[first_free_connect].conn_state != CNST_FREE )
+ {
+ syslog( LOG_CRIT, "the connects free list is messed up" );
+ exit( 1 );
+ }
+ c = &connects[first_free_connect];
+ /* Make the httpd_conn if necessary. */
+ if ( c->hc == (httpd_conn*) 0 )
+ {
+ c->hc = NEW( httpd_conn, 1 );
+ if ( c->hc == (httpd_conn*) 0 )
+ {
+ syslog( LOG_CRIT, "out of memory allocating an httpd_conn" );
+ exit( 1 );
+ }
+ c->hc->initialized = 0;
+ ++httpd_conn_count;
+ }
+
+ /* Get the connection. */
+ switch ( httpd_get_conn( hs, listen_fd, c->hc ) )
+ {
+ /* Some error happened. Run the timers, then the
+ ** existing connections. Maybe the error will clear.
+ */
+ case GC_FAIL:
+ tmr_run( tvP );
+ return 0;
+
+ /* No more connections to accept for now. */
+ case GC_NO_MORE:
+ return 1;
+ }
+ c->conn_state = CNST_READING;
+ /* Pop it off the free list. */
+ first_free_connect = c->next_free_connect;
+ c->next_free_connect = -1;
+ ++num_connects;
+ client_data.p = c;
+ c->active_at = tvP->tv_sec;
+ c->wakeup_timer = (Timer*) 0;
+ c->linger_timer = (Timer*) 0;
+ c->next_byte_index = 0;
+ c->numtnums = 0;
+
+ /* Set the connection file descriptor to no-delay mode. */
+ httpd_set_ndelay( c->hc->conn_fd );
+
+ fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ );
+
+ ++stats_connections;
+ if ( num_connects > stats_simultaneous )
+ stats_simultaneous = num_connects;
+ }
+ }
+
+
+static void
+handle_read( connecttab* c, struct timeval* tvP )
+ {
+ int sz;
+ ClientData client_data;
+ httpd_conn* hc = c->hc;
+
+ /* Is there room in our buffer to read more bytes? */
+ if ( hc->read_idx >= hc->read_size )
+ {
+ if ( hc->read_size > 5000 )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ finish_connection( c, tvP );
+ return;
+ }
+ httpd_realloc_str(
+ &hc->read_buf, &hc->read_size, hc->read_size + 1000 );
+ }
+
+ /* Read some more bytes. */
+ sz = read(
+ hc->conn_fd, &(hc->read_buf[hc->read_idx]),
+ hc->read_size - hc->read_idx );
+ if ( sz == 0 )
+ {
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ finish_connection( c, tvP );
+ return;
+ }
+ if ( sz < 0 )
+ {
+ /* Ignore EINTR and EAGAIN. Also ignore EWOULDBLOCK. At first glance
+ ** you would think that connections returned by fdwatch as readable
+ ** should never give an EWOULDBLOCK; however, this apparently can
+ ** happen if a packet gets garbled.
+ */
+ if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK )
+ return;
+ httpd_send_err(
+ hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ finish_connection( c, tvP );
+ return;
+ }
+ hc->read_idx += sz;
+ c->active_at = tvP->tv_sec;
+
+ /* Do we have a complete request yet? */
+ switch ( httpd_got_request( hc ) )
+ {
+ case GR_NO_REQUEST:
+ return;
+ case GR_BAD_REQUEST:
+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
+ finish_connection( c, tvP );
+ return;
+ }
+
+ /* Yes. Try parsing and resolving it. */
+ if ( httpd_parse_request( hc ) < 0 )
+ {
+ finish_connection( c, tvP );
+ return;
+ }
+
+ /* Check the throttle table */
+ if ( ! check_throttles( c ) )
+ {
+ httpd_send_err(
+ hc, 503, httpd_err503title, "", httpd_err503form, hc->encodedurl );
+ finish_connection( c, tvP );
+ return;
+ }
+
+ /* Start the connection going. */
+ if ( httpd_start_request( hc, tvP ) < 0 )
+ {
+ /* Something went wrong. Close down the connection. */
+ finish_connection( c, tvP );
+ return;
+ }
+
+ /* Fill in end_byte_index. */
+ if ( hc->got_range )
+ {
+ c->next_byte_index = hc->first_byte_index;
+ c->end_byte_index = hc->last_byte_index + 1;
+ }
+ else if ( hc->bytes_to_send < 0 )
+ c->end_byte_index = 0;
+ else
+ c->end_byte_index = hc->bytes_to_send;
+
+ /* Check if it's already handled. */
+ if ( hc->file_address == (char*) 0 )
+ {
+ /* No file address means someone else is handling it. */
+ int tind;
+ for ( tind = 0; tind < c->numtnums; ++tind )
+ throttles[c->tnums[tind]].bytes_since_avg += hc->bytes_sent;
+ c->next_byte_index = hc->bytes_sent;
+ finish_connection( c, tvP );
+ return;
+ }
+ if ( c->next_byte_index >= c->end_byte_index )
+ {
+ /* There's nothing to send. */
+ finish_connection( c, tvP );
+ return;
+ }
+
+ /* Cool, we have a valid connection and a file to send to it. */
+ c->conn_state = CNST_SENDING;
+ c->started_at = tvP->tv_sec;
+ c->wouldblock_delay = 0;
+ client_data.p = c;
+
+ fdwatch_del_fd( hc->conn_fd );
+ fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE );
+ }
+
+
+static void
+handle_send( connecttab* c, struct timeval* tvP )
+ {
+ size_t max_bytes;
+ int sz, coast;
+ ClientData client_data;
+ time_t elapsed;
+ httpd_conn* hc = c->hc;
+ int tind;
+
+ if ( c->max_limit == THROTTLE_NOLIMIT )
+ max_bytes = 1000000000L;
+ else
+ max_bytes = c->max_limit / 4; /* send at most 1/4 seconds worth */
+
+ /* Do we need to write the headers first? */
+ if ( hc->responselen == 0 )
+ {
+ /* No, just write the file. */
+ sz = write(
+ hc->conn_fd, &(hc->file_address[c->next_byte_index]),
+ MIN( c->end_byte_index - c->next_byte_index, max_bytes ) );
+ }
+ else
+ {
+ /* Yes. We'll combine headers and file into a single writev(),
+ ** hoping that this generates a single packet.
+ */
+ struct iovec iv[2];
+
+ iv[0].iov_base = hc->response;
+ iv[0].iov_len = hc->responselen;
+ iv[1].iov_base = &(hc->file_address[c->next_byte_index]);
+ iv[1].iov_len = MIN( c->end_byte_index - c->next_byte_index, max_bytes );
+ sz = writev( hc->conn_fd, iv, 2 );
+ }
+
+ if ( sz < 0 && errno == EINTR )
+ return;
+
+ if ( sz == 0 ||
+ ( sz < 0 && ( errno == EWOULDBLOCK || errno == EAGAIN ) ) )
+ {
+ /* This shouldn't happen, but some kernels, e.g.
+ ** SunOS 4.1.x, are broken and select() says that
+ ** O_NDELAY sockets are always writable even when
+ ** they're actually not.
+ **
+ ** Current workaround is to block sending on this
+ ** socket for a brief adaptively-tuned period.
+ ** Fortunately we already have all the necessary
+ ** blocking code, for use with throttling.
+ */
+ c->wouldblock_delay += MIN_WOULDBLOCK_DELAY;
+ c->conn_state = CNST_PAUSING;
+ fdwatch_del_fd( hc->conn_fd );
+ client_data.p = c;
+ if ( c->wakeup_timer != (Timer*) 0 )
+ syslog( LOG_ERR, "replacing non-null wakeup_timer!" );
+ c->wakeup_timer = tmr_create(
+ tvP, wakeup_connection, client_data, c->wouldblock_delay, 0 );
+ if ( c->wakeup_timer == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(wakeup_connection) failed" );
+ exit( 1 );
+ }
+ return;
+ }
+
+ if ( sz < 0 )
+ {
+ /* Something went wrong, close this connection.
+ **
+ ** If it's just an EPIPE, don't bother logging, that
+ ** just means the client hung up on us.
+ **
+ ** On some systems, write() occasionally gives an EINVAL.
+ ** Dunno why, something to do with the socket going
+ ** bad. Anyway, we don't log those either.
+ **
+ ** And ECONNRESET isn't interesting either.
+ */
+ if ( errno != EPIPE && errno != EINVAL && errno != ECONNRESET )
+ syslog( LOG_ERR, "write - %m sending %.80s", hc->encodedurl );
+ clear_connection( c, tvP );
+ return;
+ }
+
+ /* Ok, we wrote something. */
+ c->active_at = tvP->tv_sec;
+ /* Was this a headers + file writev()? */
+ if ( hc->responselen > 0 )
+ {
+ /* Yes; did we write only part of the headers? */
+ if ( sz < hc->responselen )
+ {
+ /* Yes; move the unwritten part to the front of the buffer. */
+ int newlen = hc->responselen - sz;
+ (void) memmove( hc->response, &(hc->response[sz]), newlen );
+ hc->responselen = newlen;
+ sz = 0;
+ }
+ else
+ {
+ /* Nope, we wrote the full headers, so adjust accordingly. */
+ sz -= hc->responselen;
+ hc->responselen = 0;
+ }
+ }
+ /* And update how much of the file we wrote. */
+ c->next_byte_index += sz;
+ c->hc->bytes_sent += sz;
+ for ( tind = 0; tind < c->numtnums; ++tind )
+ throttles[c->tnums[tind]].bytes_since_avg += sz;
+
+ /* Are we done? */
+ if ( c->next_byte_index >= c->end_byte_index )
+ {
+ /* This connection is finished! */
+ finish_connection( c, tvP );
+ return;
+ }
+
+ /* Tune the (blockheaded) wouldblock delay. */
+ if ( c->wouldblock_delay > MIN_WOULDBLOCK_DELAY )
+ c->wouldblock_delay -= MIN_WOULDBLOCK_DELAY;
+
+ /* If we're throttling, check if we're sending too fast. */
+ if ( c->max_limit != THROTTLE_NOLIMIT )
+ {
+ elapsed = tvP->tv_sec - c->started_at;
+ if ( elapsed == 0 )
+ elapsed = 1; /* count at least one second */
+ if ( c->hc->bytes_sent / elapsed > c->max_limit )
+ {
+ c->conn_state = CNST_PAUSING;
+ fdwatch_del_fd( hc->conn_fd );
+ /* How long should we wait to get back on schedule? If less
+ ** than a second (integer math rounding), use 1/2 second.
+ */
+ coast = c->hc->bytes_sent / c->max_limit - elapsed;
+ client_data.p = c;
+ if ( c->wakeup_timer != (Timer*) 0 )
+ syslog( LOG_ERR, "replacing non-null wakeup_timer!" );
+ c->wakeup_timer = tmr_create(
+ tvP, wakeup_connection, client_data,
+ coast > 0 ? ( coast * 1000L ) : 500L, 0 );
+ if ( c->wakeup_timer == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(wakeup_connection) failed" );
+ exit( 1 );
+ }
+ }
+ }
+ /* (No check on min_limit here, that only controls connection startups.) */
+ }
+
+
+static void
+handle_linger( connecttab* c, struct timeval* tvP )
+ {
+ char buf[4096];
+ int r;
+
+ /* In lingering-close mode we just read and ignore bytes. An error
+ ** or EOF ends things, otherwise we go until a timeout.
+ */
+ r = read( c->hc->conn_fd, buf, sizeof(buf) );
+ if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) )
+ return;
+ if ( r <= 0 )
+ really_clear_connection( c, tvP );
+ }
+
+
+static int
+check_throttles( connecttab* c )
+ {
+ int tnum;
+ long l;
+
+ c->numtnums = 0;
+ c->max_limit = c->min_limit = THROTTLE_NOLIMIT;
+ for ( tnum = 0; tnum < numthrottles && c->numtnums < MAXTHROTTLENUMS;
+ ++tnum )
+ if ( match( throttles[tnum].pattern, c->hc->expnfilename ) )
+ {
+ /* If we're way over the limit, don't even start. */
+ if ( throttles[tnum].rate > throttles[tnum].max_limit * 2 )
+ return 0;
+ /* Also don't start if we're under the minimum. */
+ if ( throttles[tnum].rate < throttles[tnum].min_limit )
+ return 0;
+ if ( throttles[tnum].num_sending < 0 )
+ {
+ syslog( LOG_ERR, "throttle sending count was negative - shouldn't happen!" );
+ throttles[tnum].num_sending = 0;
+ }
+ c->tnums[c->numtnums++] = tnum;
+ ++throttles[tnum].num_sending;
+ l = throttles[tnum].max_limit / throttles[tnum].num_sending;
+ if ( c->max_limit == THROTTLE_NOLIMIT )
+ c->max_limit = l;
+ else
+ c->max_limit = MIN( c->max_limit, l );
+ l = throttles[tnum].min_limit;
+ if ( c->min_limit == THROTTLE_NOLIMIT )
+ c->min_limit = l;
+ else
+ c->min_limit = MAX( c->min_limit, l );
+ }
+ return 1;
+ }
+
+
+static void
+clear_throttles( connecttab* c, struct timeval* tvP )
+ {
+ int tind;
+
+ for ( tind = 0; tind < c->numtnums; ++tind )
+ --throttles[c->tnums[tind]].num_sending;
+ }
+
+
+static void
+update_throttles( ClientData client_data, struct timeval* nowP )
+ {
+ int tnum, tind;
+ int cnum;
+ connecttab* c;
+ long l;
+
+ /* Update the average sending rate for each throttle. This is only used
+ ** when new connections start up.
+ */
+ for ( tnum = 0; tnum < numthrottles; ++tnum )
+ {
+ throttles[tnum].rate = ( 2 * throttles[tnum].rate + throttles[tnum].bytes_since_avg / THROTTLE_TIME ) / 3;
+ throttles[tnum].bytes_since_avg = 0;
+ /* Log a warning message if necessary. */
+ if ( throttles[tnum].rate > throttles[tnum].max_limit && throttles[tnum].num_sending != 0 )
+ {
+ if ( throttles[tnum].rate > throttles[tnum].max_limit * 2 )
+ syslog( LOG_NOTICE, "throttle #%d '%.80s' rate %ld greatly exceeding limit %ld; %d sending", tnum, throttles[tnum].pattern, throttles[tnum].rate, throttles[tnum].max_limit, throttles[tnum].num_sending );
+ else
+ syslog( LOG_INFO, "throttle #%d '%.80s' rate %ld exceeding limit %ld; %d sending", tnum, throttles[tnum].pattern, throttles[tnum].rate, throttles[tnum].max_limit, throttles[tnum].num_sending );
+ }
+ if ( throttles[tnum].rate < throttles[tnum].min_limit && throttles[tnum].num_sending != 0 )
+ {
+ syslog( LOG_NOTICE, "throttle #%d '%.80s' rate %ld lower than minimum %ld; %d sending", tnum, throttles[tnum].pattern, throttles[tnum].rate, throttles[tnum].min_limit, throttles[tnum].num_sending );
+ }
+ }
+
+ /* Now update the sending rate on all the currently-sending connections,
+ ** redistributing it evenly.
+ */
+ for ( cnum = 0; cnum < max_connects; ++cnum )
+ {
+ c = &connects[cnum];
+ if ( c->conn_state == CNST_SENDING || c->conn_state == CNST_PAUSING )
+ {
+ c->max_limit = THROTTLE_NOLIMIT;
+ for ( tind = 0; tind < c->numtnums; ++tind )
+ {
+ tnum = c->tnums[tind];
+ l = throttles[tnum].max_limit / throttles[tnum].num_sending;
+ if ( c->max_limit == THROTTLE_NOLIMIT )
+ c->max_limit = l;
+ else
+ c->max_limit = MIN( c->max_limit, l );
+ }
+ }
+ }
+ }
+
+
+static void
+finish_connection( connecttab* c, struct timeval* tvP )
+ {
+ /* If we haven't actually sent the buffered response yet, do so now. */
+ httpd_write_response( c->hc );
+
+ /* And clear. */
+ clear_connection( c, tvP );
+ }
+
+
+static void
+clear_connection( connecttab* c, struct timeval* tvP )
+ {
+ ClientData client_data;
+
+ if ( c->wakeup_timer != (Timer*) 0 )
+ {
+ tmr_cancel( c->wakeup_timer );
+ c->wakeup_timer = 0;
+ }
+
+ /* This is our version of Apache's lingering_close() routine, which is
+ ** their version of the often-broken SO_LINGER socket option. For why
+ ** this is necessary, see http://www.apache.org/docs/misc/fin_wait_2.html
+ ** What we do is delay the actual closing for a few seconds, while reading
+ ** any bytes that come over the connection. However, we don't want to do
+ ** this unless it's necessary, because it ties up a connection slot and
+ ** file descriptor which means our maximum connection-handling rate
+ ** is lower. So, elsewhere we set a flag when we detect the few
+ ** circumstances that make a lingering close necessary. If the flag
+ ** isn't set we do the real close now.
+ */
+ if ( c->conn_state == CNST_LINGERING )
+ {
+ /* If we were already lingering, shut down for real. */
+ tmr_cancel( c->linger_timer );
+ c->linger_timer = (Timer*) 0;
+ c->hc->should_linger = 0;
+ }
+ if ( c->hc->should_linger )
+ {
+ if ( c->conn_state != CNST_PAUSING )
+ fdwatch_del_fd( c->hc->conn_fd );
+ c->conn_state = CNST_LINGERING;
+ shutdown( c->hc->conn_fd, SHUT_WR );
+ fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ );
+ client_data.p = c;
+ if ( c->linger_timer != (Timer*) 0 )
+ syslog( LOG_ERR, "replacing non-null linger_timer!" );
+ c->linger_timer = tmr_create(
+ tvP, linger_clear_connection, client_data, LINGER_TIME, 0 );
+ if ( c->linger_timer == (Timer*) 0 )
+ {
+ syslog( LOG_CRIT, "tmr_create(linger_clear_connection) failed" );
+ exit( 1 );
+ }
+ }
+ else
+ really_clear_connection( c, tvP );
+ }
+
+
+static void
+really_clear_connection( connecttab* c, struct timeval* tvP )
+ {
+ stats_bytes += c->hc->bytes_sent;
+ if ( c->conn_state != CNST_PAUSING )
+ fdwatch_del_fd( c->hc->conn_fd );
+ httpd_close_conn( c->hc, tvP );
+ clear_throttles( c, tvP );
+ if ( c->linger_timer != (Timer*) 0 )
+ {
+ tmr_cancel( c->linger_timer );
+ c->linger_timer = 0;
+ }
+ c->conn_state = CNST_FREE;
+ c->next_free_connect = first_free_connect;
+ first_free_connect = c - connects; /* division by sizeof is implied */
+ --num_connects;
+ }
+
+
+static void
+idle( ClientData client_data, struct timeval* nowP )
+ {
+ int cnum;
+ connecttab* c;
+
+ for ( cnum = 0; cnum < max_connects; ++cnum )
+ {
+ c = &connects[cnum];
+ switch ( c->conn_state )
+ {
+ case CNST_READING:
+ if ( nowP->tv_sec - c->active_at >= IDLE_READ_TIMELIMIT )
+ {
+ syslog( LOG_INFO,
+ "%.80s connection timed out reading",
+ httpd_ntoa( &c->hc->client_addr ) );
+ httpd_send_err(
+ c->hc, 408, httpd_err408title, "", httpd_err408form, "" );
+ finish_connection( c, nowP );
+ }
+ break;
+ case CNST_SENDING:
+ case CNST_PAUSING:
+ if ( nowP->tv_sec - c->active_at >= IDLE_SEND_TIMELIMIT )
+ {
+ syslog( LOG_INFO,
+ "%.80s connection timed out sending",
+ httpd_ntoa( &c->hc->client_addr ) );
+ clear_connection( c, nowP );
+ }
+ break;
+ }
+ }
+ }
+
+
+static void
+wakeup_connection( ClientData client_data, struct timeval* nowP )
+ {
+ connecttab* c;
+
+ c = (connecttab*) client_data.p;
+ c->wakeup_timer = (Timer*) 0;
+ if ( c->conn_state == CNST_PAUSING )
+ {
+ c->conn_state = CNST_SENDING;
+ fdwatch_add_fd( c->hc->conn_fd, c, FDW_WRITE );
+ }
+ }
+
+static void
+linger_clear_connection( ClientData client_data, struct timeval* nowP )
+ {
+ connecttab* c;
+
+ c = (connecttab*) client_data.p;
+ c->linger_timer = (Timer*) 0;
+ really_clear_connection( c, nowP );
+ }
+
+
+static void
+occasional( ClientData client_data, struct timeval* nowP )
+ {
+ mmc_cleanup( nowP );
+ tmr_cleanup();
+ watchdog_flag = 1; /* let the watchdog know that we are alive */
+ }
+
+
+#ifdef STATS_TIME
+static void
+show_stats( ClientData client_data, struct timeval* nowP )
+ {
+ logstats( nowP );
+ }
+#endif /* STATS_TIME */
+
+
+/* Generate debugging statistics syslog messages for all packages. */
+static void
+logstats( struct timeval* nowP )
+ {
+ struct timeval tv;
+ time_t now;
+ long up_secs, stats_secs;
+
+ if ( nowP == (struct timeval*) 0 )
+ {
+ (void) gettimeofday( &tv, (struct timezone*) 0 );
+ nowP = &tv;
+ }
+ now = nowP->tv_sec;
+ up_secs = now - start_time;
+ stats_secs = now - stats_time;
+ if ( stats_secs == 0 )
+ stats_secs = 1; /* fudge */
+ stats_time = now;
+ syslog( LOG_NOTICE,
+ "up %ld seconds, stats for %ld seconds:", up_secs, stats_secs );
+
+ thttpd_logstats( stats_secs );
+ httpd_logstats( stats_secs );
+ mmc_logstats( stats_secs );
+ fdwatch_logstats( stats_secs );
+ tmr_logstats( stats_secs );
+ }
+
+
+/* Generate debugging statistics syslog message. */
+static void
+thttpd_logstats( long secs )
+ {
+ if ( secs > 0 )
+ syslog( LOG_NOTICE,
+ " thttpd - %ld connections (%g/sec), %d max simultaneous, %lld bytes (%g/sec), %d httpd_conns allocated",
+ stats_connections, (float) stats_connections / secs,
+ stats_simultaneous, (long long) stats_bytes,
+ (float) stats_bytes / secs, httpd_conn_count );
+ stats_connections = 0;
+ stats_bytes = 0;
+ stats_simultaneous = 0;
+ }
--- /dev/null
+/* timers.c - simple timer routines
+**
+** Copyright © 1995,1998,2000,2014 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <syslog.h>
+
+#include "timers.h"
+
+
+#define HASH_SIZE 67
+static Timer* timers[HASH_SIZE];
+static Timer* free_timers;
+static int alloc_count, active_count, free_count;
+
+ClientData JunkClientData;
+
+
+
+static unsigned int
+hash( Timer* t )
+ {
+ /* We can hash on the trigger time, even though it can change over
+ ** the life of a timer via either the periodic bit or the tmr_reset()
+ ** call. This is because both of those guys call l_resort(), which
+ ** recomputes the hash and moves the timer to the appropriate list.
+ */
+ return (
+ (unsigned int) t->time.tv_sec ^
+ (unsigned int) t->time.tv_usec ) % HASH_SIZE;
+ }
+
+
+static void
+l_add( Timer* t )
+ {
+ int h = t->hash;
+ Timer* t2;
+ Timer* t2prev;
+
+ t2 = timers[h];
+ if ( t2 == (Timer*) 0 )
+ {
+ /* The list is empty. */
+ timers[h] = t;
+ t->prev = t->next = (Timer*) 0;
+ }
+ else
+ {
+ if ( t->time.tv_sec < t2->time.tv_sec ||
+ ( t->time.tv_sec == t2->time.tv_sec &&
+ t->time.tv_usec <= t2->time.tv_usec ) )
+ {
+ /* The new timer goes at the head of the list. */
+ timers[h] = t;
+ t->prev = (Timer*) 0;
+ t->next = t2;
+ t2->prev = t;
+ }
+ else
+ {
+ /* Walk the list to find the insertion point. */
+ for ( t2prev = t2, t2 = t2->next; t2 != (Timer*) 0;
+ t2prev = t2, t2 = t2->next )
+ {
+ if ( t->time.tv_sec < t2->time.tv_sec ||
+ ( t->time.tv_sec == t2->time.tv_sec &&
+ t->time.tv_usec <= t2->time.tv_usec ) )
+ {
+ /* Found it. */
+ t2prev->next = t;
+ t->prev = t2prev;
+ t->next = t2;
+ t2->prev = t;
+ return;
+ }
+ }
+ /* Oops, got to the end of the list. Add to tail. */
+ t2prev->next = t;
+ t->prev = t2prev;
+ t->next = (Timer*) 0;
+ }
+ }
+ }
+
+
+static void
+l_remove( Timer* t )
+ {
+ int h = t->hash;
+
+ if ( t->prev == (Timer*) 0 )
+ timers[h] = t->next;
+ else
+ t->prev->next = t->next;
+ if ( t->next != (Timer*) 0 )
+ t->next->prev = t->prev;
+ }
+
+
+static void
+l_resort( Timer* t )
+ {
+ /* Remove the timer from its old list. */
+ l_remove( t );
+ /* Recompute the hash. */
+ t->hash = hash( t );
+ /* And add it back in to its new list, sorted correctly. */
+ l_add( t );
+ }
+
+
+void
+tmr_init( void )
+ {
+ int h;
+
+ for ( h = 0; h < HASH_SIZE; ++h )
+ timers[h] = (Timer*) 0;
+ free_timers = (Timer*) 0;
+ alloc_count = active_count = free_count = 0;
+ }
+
+
+Timer*
+tmr_create(
+ struct timeval* nowP, TimerProc* timer_proc, ClientData client_data,
+ long msecs, int periodic )
+ {
+ Timer* t;
+
+ if ( free_timers != (Timer*) 0 )
+ {
+ t = free_timers;
+ free_timers = t->next;
+ --free_count;
+ }
+ else
+ {
+ t = (Timer*) malloc( sizeof(Timer) );
+ if ( t == (Timer*) 0 )
+ return (Timer*) 0;
+ ++alloc_count;
+ }
+
+ t->timer_proc = timer_proc;
+ t->client_data = client_data;
+ t->msecs = msecs;
+ t->periodic = periodic;
+ if ( nowP != (struct timeval*) 0 )
+ t->time = *nowP;
+ else
+ (void) gettimeofday( &t->time, (struct timezone*) 0 );
+ t->time.tv_sec += msecs / 1000L;
+ t->time.tv_usec += ( msecs % 1000L ) * 1000L;
+ if ( t->time.tv_usec >= 1000000L )
+ {
+ t->time.tv_sec += t->time.tv_usec / 1000000L;
+ t->time.tv_usec %= 1000000L;
+ }
+ t->hash = hash( t );
+ /* Add the new timer to the proper active list. */
+ l_add( t );
+ ++active_count;
+
+ return t;
+ }
+
+
+struct timeval*
+tmr_timeout( struct timeval* nowP )
+ {
+ long msecs;
+ static struct timeval timeout;
+
+ msecs = tmr_mstimeout( nowP );
+ if ( msecs == INFTIM )
+ return (struct timeval*) 0;
+ timeout.tv_sec = msecs / 1000L;
+ timeout.tv_usec = ( msecs % 1000L ) * 1000L;
+ return &timeout;
+ }
+
+
+long
+tmr_mstimeout( struct timeval* nowP )
+ {
+ int h;
+ int gotone;
+ long msecs, m;
+ Timer* t;
+
+ gotone = 0;
+ msecs = 0; /* make lint happy */
+ /* Since the lists are sorted, we only need to look at the
+ ** first timer on each one.
+ */
+ for ( h = 0; h < HASH_SIZE; ++h )
+ {
+ t = timers[h];
+ if ( t != (Timer*) 0 )
+ {
+ m = ( t->time.tv_sec - nowP->tv_sec ) * 1000L +
+ ( t->time.tv_usec - nowP->tv_usec ) / 1000L;
+ if ( ! gotone )
+ {
+ msecs = m;
+ gotone = 1;
+ }
+ else if ( m < msecs )
+ msecs = m;
+ }
+ }
+ if ( ! gotone )
+ return INFTIM;
+ if ( msecs <= 0 )
+ msecs = 0;
+ return msecs;
+ }
+
+
+void
+tmr_run( struct timeval* nowP )
+ {
+ int h;
+ Timer* t;
+ Timer* next;
+
+ for ( h = 0; h < HASH_SIZE; ++h )
+ for ( t = timers[h]; t != (Timer*) 0; t = next )
+ {
+ next = t->next;
+ /* Since the lists are sorted, as soon as we find a timer
+ ** that isn't ready yet, we can go on to the next list.
+ */
+ if ( t->time.tv_sec > nowP->tv_sec ||
+ ( t->time.tv_sec == nowP->tv_sec &&
+ t->time.tv_usec > nowP->tv_usec ) )
+ break;
+ (t->timer_proc)( t->client_data, nowP );
+ if ( t->periodic )
+ {
+ /* Reschedule. */
+ t->time.tv_sec += t->msecs / 1000L;
+ t->time.tv_usec += ( t->msecs % 1000L ) * 1000L;
+ if ( t->time.tv_usec >= 1000000L )
+ {
+ t->time.tv_sec += t->time.tv_usec / 1000000L;
+ t->time.tv_usec %= 1000000L;
+ }
+ l_resort( t );
+ }
+ else
+ tmr_cancel( t );
+ }
+ }
+
+
+void
+tmr_reset( struct timeval* nowP, Timer* t )
+ {
+ t->time = *nowP;
+ t->time.tv_sec += t->msecs / 1000L;
+ t->time.tv_usec += ( t->msecs % 1000L ) * 1000L;
+ if ( t->time.tv_usec >= 1000000L )
+ {
+ t->time.tv_sec += t->time.tv_usec / 1000000L;
+ t->time.tv_usec %= 1000000L;
+ }
+ l_resort( t );
+ }
+
+
+void
+tmr_cancel( Timer* t )
+ {
+ /* Remove it from its active list. */
+ l_remove( t );
+ --active_count;
+ /* And put it on the free list. */
+ t->next = free_timers;
+ free_timers = t;
+ ++free_count;
+ t->prev = (Timer*) 0;
+ }
+
+
+void
+tmr_cleanup( void )
+ {
+ Timer* t;
+
+ while ( free_timers != (Timer*) 0 )
+ {
+ t = free_timers;
+ free_timers = t->next;
+ --free_count;
+ free( (void*) t );
+ --alloc_count;
+ }
+ }
+
+
+void
+tmr_term( void )
+ {
+ int h;
+
+ for ( h = 0; h < HASH_SIZE; ++h )
+ while ( timers[h] != (Timer*) 0 )
+ tmr_cancel( timers[h] );
+ tmr_cleanup();
+ }
+
+
+/* Generate debugging statistics syslog message. */
+void
+tmr_logstats( long secs )
+ {
+ syslog(
+ LOG_NOTICE, " timers - %d allocated, %d active, %d free",
+ alloc_count, active_count, free_count );
+ if ( active_count + free_count != alloc_count )
+ syslog( LOG_ERR, "timer counts don't add up!" );
+ }
--- /dev/null
+/* timers.h - header file for timers package
+**
+** Copyright © 1995,1998,1999,2000,2014 by Jef Poskanzer <jef@mail.acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#ifndef _TIMERS_H_
+#define _TIMERS_H_
+
+#include <sys/time.h>
+
+#ifndef INFTIM
+#define INFTIM -1
+#endif /* INFTIM */
+
+/* ClientData is a random value that tags along with a timer. The client
+** can use it for whatever, and it gets passed to the callback when the
+** timer triggers.
+*/
+typedef union {
+ void* p;
+ int i;
+ long l;
+ } ClientData;
+
+extern ClientData JunkClientData; /* for use when you don't care */
+
+/* The TimerProc gets called when the timer expires. It gets passed
+** the ClientData associated with the timer, and a timeval in case
+** it wants to schedule another timer.
+*/
+typedef void TimerProc( ClientData client_data, struct timeval* nowP );
+
+/* The Timer struct. */
+typedef struct TimerStruct {
+ TimerProc* timer_proc;
+ ClientData client_data;
+ long msecs;
+ int periodic;
+ struct timeval time;
+ struct TimerStruct* prev;
+ struct TimerStruct* next;
+ int hash;
+ } Timer;
+
+/* Initialize the timer package. */
+void tmr_init( void );
+
+/* Set up a timer, either periodic or one-shot. Returns (Timer*) 0 on errors. */
+Timer* tmr_create(
+ struct timeval* nowP, TimerProc* timer_proc, ClientData client_data,
+ long msecs, int periodic );
+
+/* Returns a timeout indicating how long until the next timer triggers. You
+** can just put the call to this routine right in your select(). Returns
+** (struct timeval*) 0 if no timers are pending.
+*/
+struct timeval* tmr_timeout( struct timeval* nowP );
+
+/* Returns a timeout in milliseconds indicating how long until the next timer
+** triggers. You can just put the call to this routine right in your poll().
+** Returns INFTIM (-1) if no timers are pending.
+*/
+long tmr_mstimeout( struct timeval* nowP );
+
+/* Run the list of timers. Your main program needs to call this every so often,
+** or as indicated by tmr_timeout().
+*/
+void tmr_run( struct timeval* nowP );
+
+/* Reset the clock on a timer, to current time plus the original timeout. */
+void tmr_reset( struct timeval* nowP, Timer* timer );
+
+/* Deschedule a timer. Note that non-periodic timers are automatically
+** descheduled when they run, so you don't have to call this on them.
+*/
+void tmr_cancel( Timer* timer );
+
+/* Clean up the timers package, freeing any unused storage. */
+void tmr_cleanup( void );
+
+/* Cancel all timers and free storage, usually in preparation for exiting. */
+void tmr_term( void );
+
+/* Generate debugging statistics syslog message. */
+void tmr_logstats( long secs );
+
+#endif /* _TIMERS_H_ */
--- /dev/null
+/* version.h - version defines for thttpd and libhttpd */
+
+#ifndef _VERSION_H_
+#define _VERSION_H_
+
+#define SERVER_SOFTWARE "thttpd/2.29 23May2018"
+#define SERVER_ADDRESS "http://www.acme.com/software/thttpd/"
+
+#endif /* _VERSION_H_ */