Import from upstream 2.29
This commit is contained in:
commit
eb3efcc450
|
@ -0,0 +1,51 @@
|
|||
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
|
|
@ -0,0 +1,40 @@
|
|||
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.
|
|
@ -0,0 +1,173 @@
|
|||
# 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
|
|
@ -0,0 +1,31 @@
|
|||
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/
|
|
@ -0,0 +1,80 @@
|
|||
- - - - - - - - - - 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
|
|
@ -0,0 +1,188 @@
|
|||
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])
|
|
@ -0,0 +1,29 @@
|
|||
#!/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
|
|
@ -0,0 +1,86 @@
|
|||
# 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
|
|
@ -0,0 +1,69 @@
|
|||
/* 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 );
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
.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.
|
|
@ -0,0 +1,215 @@
|
|||
/* 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 );
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
.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.
|
|
@ -0,0 +1,763 @@
|
|||
/* 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 );
|
||||
}
|
|
@ -0,0 +1,693 @@
|
|||
#! /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
|
|
@ -0,0 +1,392 @@
|
|||
/* 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_ */
|
|
@ -0,0 +1,927 @@
|
|||
#! /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
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,138 @@
|
|||
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)
|
|
@ -0,0 +1,14 @@
|
|||
# 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
|
|
@ -0,0 +1,47 @@
|
|||
#!/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 ''
|
|
@ -0,0 +1,154 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# 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
|
|
@ -0,0 +1,16 @@
|
|||
.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.
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
.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.
|
|
@ -0,0 +1,256 @@
|
|||
/* 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 );
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#!/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
|
|
@ -0,0 +1,45 @@
|
|||
.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.
|
|
@ -0,0 +1,834 @@
|
|||
/* 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 */
|
|
@ -0,0 +1,85 @@
|
|||
/* 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_ */
|
|
@ -0,0 +1,14 @@
|
|||
<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>
|
|
@ -0,0 +1,250 @@
|
|||
#! /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
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,291 @@
|
|||
/* 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_ */
|
|
@ -0,0 +1,88 @@
|
|||
/* 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;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* 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_ */
|
|
@ -0,0 +1,8 @@
|
|||
# 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
|
|
@ -0,0 +1,198 @@
|
|||
# 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
|
|
@ -0,0 +1,531 @@
|
|||
/* 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!" );
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/* 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_ */
|
|
@ -0,0 +1,19 @@
|
|||
#!/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
|
|
@ -0,0 +1,47 @@
|
|||
#!/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"
|
|
@ -0,0 +1,23 @@
|
|||
#!/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
|
||||
) &
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
|
@ -0,0 +1,328 @@
|
|||
/* 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;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* 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_ */
|
|
@ -0,0 +1,596 @@
|
|||
.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.
|
|
@ -0,0 +1,351 @@
|
|||
/* 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!" );
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/* 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_ */
|
Loading…
Reference in New Issue