1
0
Fork 0

Initial git commit with version 1.4

This commit is contained in:
Kim Holviala 2014-01-25 11:21:40 +02:00
commit d829e6a347
37 changed files with 5163 additions and 0 deletions

251
ChangeLog Normal file
View File

@ -0,0 +1,251 @@
2012-12-02 Kim Holviala <kim@holviala.com>
* Released version 1.4
* Added logcheck ignore file for Debian
* Fixed compile without HAVE_SHMEM
* Autogenerated caps.txt now works without SHMEM
* Support for Haiku R1 (make && make install works)
* CGIs now have $LOCAL_ADDR
* Debian package no longer depends on lsb-release
* CPU type is now properly detected on AIX
* Makefile supports cross-compiling (CC & HOSTCC)
* Option -nr disables root user checking (for debugging)
* Platform detection for Linux/mips boards (routers)
* Fixes for OpenBSD (thanks to Brian Callahan)
* Last remaining sprintf() replaced with snprintf()
* max() is no longer a function but a #define
* Clang fixes (thanks to Jacob Dahl Pind)
* Removed system-info.sh & dmidecode from Debian package
2012-06-12 Kim Holviala <kim@holviala.com>
* Released version 1.3
* Support for headerless HTTP/0.9
* Code cleanups
* Platform probing now knows about RedHat and Slackware
* lsb_release no longer gets called if it doesn't exist
(bugreport from Jacob Dahl Pind)
* Changed menu errors from type "i" text to type "3"
(bugreport from Damien Carol)
* Removed the special OSX Carbonized build
* Fixed a bug in menu.c: popen() needs pclose()
* Fixed a off-by-one in gopher_filetype()
* Changed the filetype of documents (doc/ps/pdf) to "d"
2012-05-04 Kim Holviala <kim@holviala.com>
* Released version 1.2 (finally...)
* On the fly selector rewriting (like Apache mod_rewrite)
* Gophertags are properly converted to output charset
* Server admin email can be specified for caps.txt
* Server location for caps.txt
* Split options.c from gophernicus.c
* Removed support for Gopher over HTTP proxies
* Hack to make "gopher example.com" work
(UMN gopher client assumes gopher+ which we don't support)
2010-12-01 Kim Holviala <kim@holviala.com>
* Released version 1.1
* Content-based detection of gif/png/jpg/ps/pdf/html/gz
* Gophermap virtual host list (%) only lists FQDNs
* Serve out caps.txt from a file if it exists
* Option -na disables autogenerated caps.txt
* Changed option -l to -b (show BSD license)
* Changed option -m to -l (log to file)
* README and LICENSE weren't zero-terminated strings (duh)
* Querying /server-status no longer updates statistics
(because Munin statistics collection was being throttled)
* Internal charset variables are now enums and not strings
2010-10-05 Kim Holviala <kim@holviala.com>
* Released version 1.0
* Support for caps.txt as suggested by Cameron Kaiser
* Support for gophertags (lifted from Bucktooth)
* HTTP requests are redirected to a public gopher proxy
* Allow directories named "gophermap" and "gophertag"
(only files are special)
* Removed duplicate call to strniconv()
* A few ENABLE_STRICT_RFC1436 additions
* Much more descriptive error logging
* Self references /./ are removed from request
* Apache-compatible file logging in combined log format (-m)
* FIFOs in directories no longer crash the server (duh!)
* Support for Mac OS X (tested with 10.5 on Intel)
* Reworked Makefile with platform-specific build targets
* Fixed a call to dirname(path) (don't assume it modifies path)
* Makefile installer now supports xinetd and launchd
* Makefile installer installs default /var/gopher/gophermap and
links the document directory as /docs/
* Added SERVER_ARCH, SERVER_VERSION and SERVER_DESCRIPTION to
CGI env variables
* Fixed a segfault where shm was used uninitialized (duh!)
* Generate native Debian/Ubuntu package with "make deb"
* platform() now tries to figure out Linux distribution
* platform() knows about Linux ARM boards
* Added argument -nm (No shared Memory) for debugging
* Fixed AIX make glitch when compiling bin2c (bug in make?)
* Changed the name of the project from "Gophernicus Server"
to plain "Gophernicus"
* Menus without footer (-nf) were missing the dot at the end
* Footer message is now right-aligned
* server-status and caps.txt requests now update sessions
* Compile-time option ENABLE_AUTOHIDING hides manually listed
resources from generated menus (to prevent double listings)
2010-07-03 Kim Holviala <kim@holviala.com>
* Released version 0.9
* Added option to disable HTTP-style query strings
* Fixed a regression where some binary files were served out
as text (which broke them)
* BinHex files are now mapped to filetype 4
* Disabling vhosting disables sessions (mostly)
2010-04-30 Kim Holviala <kim@holviala.com>
* Released version 0.8
* Security bug in hURL handler fixed
* Error pages are now correctly generated for type 'h'
* Menu error page more compatible with clients
* New macro sstrncmp() compares without explicit sizeof()
* Removed all traces of gopher++ protocol (extra headers)
as it just didn't work with older (circa '92) servers
* Added option to disable automatic menu headers (titles)
* Do a chdir() to the resource dir before doing anything
* Double-slashes were slashed in QUERY_STRING by accident
* Relative links to external hosts work properly in gophermap
* Gophermaps can include other gophermaps with =/path/to/file
* Executable gophermaps are parsed just like static ones
2010-04-13 Kim Holviala <kim@holviala.com>
* Released version 0.7
* This release is feature complete, no new features in sight
* Support for NetBSD (a typo prevented building - duh)
* Replaced the poorly-working scandir() with opendir/qsort
* Directory listings (menus) are limited to 1024 entries
* Changed the filetype of movies from "v" to ";" (which sucks)
* Fixed a compatibility issue with bucktooth gophermaps
* Finally wrote decent documentation (README and INSTALL)
2010-04-11 Kim Holviala <kim@holviala.com>
* Released version 0.6
* platform() results are kept in shared memory
* Support for AIX 5.1 and newer
* IPv4-in-IPv6 prefix ::ffff: is removed from remote_addr
* Replaced install(1) with the install-sh script
* /server-status CPULoad can be parsed from /usr/bin/uptime
* Replaced text2c/hexdump with bin2c.c (less dependencies)
* Files with extension .q (type 7 query) are considered CGIs
* Filetype handling completely rewritten
* Configurable gopher filetypes using the "-e ext=X" argument
* Per-directory filetype overrides in gophermaps with ":ext=X"
* Refuse to serve out gophermaps (why didn't I catch this before?)
* Cleaned up main()
* Output filters - run files through an external program (php!)
2010-04-05 Kim Holviala <kim@holviala.com>
* Released version 0.5
* Code tested to work on 32-bit Linux/armv5tel
* Filetype 7 query errors are now handled properly
* HTTP-style query string overrides type 7 query
* Protocol detection (0/+/++) works properly
* gopher++ extra headers parsed correctly
* gopher++ works ok with a patched NSCA Mosaic!
* ISO-8859-1 (Latin-1) output
* Full UTF-8 output support (without widechars)
* Gophermaps are converted to output charset
* All type 0 output is converted to output charset
* All charset conversions can be disabled with option -no
* !Titles in gophermaps are converted to gopher menu titles
* Automatically generates gopher title resources for menus
* Compile-time option to strictly adhere to RFC 1436
* Compile-time option to disable all gopher++ support
2010-03-29 Kim Holviala <kim@holviala.com>
* Released version 0.4
* Renamed the project to "Gophernicus Server"
* Major rewrite with much cleaner code
* Changed all strncpy's to the OpenBSD strlcpy
* Server can guess the request type (menu/text/binary)
* Errors are formatted for current filetype (menu/text)
* Errors for images (types g&I) are outputted as an image
* /~luser (/home/luser/public_gopher) must be owned by luser
* Configurable output width for menus
* Files are outputted using sendfile() if available
* Locale forced to POSIX for strftime()
* Filetype '-' in gophermaps hides files
* Gopher+ requests are now handled gracefully
* Relative selectors in gophemaps work
* Filesizes in menus are now human-readable (KB/MB/GB etc)
* Refuse to serve world-writeable content
* Support for Apache-style /server-status
* HTTP requests for /server-status work (munin monitoring ftw!)
* Session tracking using shared memory
* Referer support for CGIs
* Replaced iconv() with own charset conversion routine
* Automatic throttling for users who hit the server too much
* Replaced static compile-time uname with uname()
* Support for virtual hosting (with gopher0 no less!)
2010-01-07 Kim Holviala <kim@holviala.com>
* Released version 0.3
* Automatic detection of text vs. binary filetype for files
which have no (known) suffix
* hURL redirect pages now respect -f (no footer) option
* IPv6 support for logging & CGI REMOTE_ADDR
* Inline gophermaps
* Removed support for relative resource names in gophermaps
* Support for virtual userdirs (~user -> /home/user/public_gopher)
* Automatic listing of userdirs in gophermap
* Redirect accidental http requests to gopher
* License included in the binary -> install no longer installs docs
* Changed command line options (I was running out of arg letters...)
* Debug to syslog with '-d' option
2010-01-02 Kim Holviala <kim@holviala.com>
* Released version 0.2
* Logging to syslog
* Support for gophermaps
* Support for executable gophermaps
* Support for CGI scripts
* Support for type 7 search queries
* Support for hURL redirect pages
* Support for non-ASCII resource/file names (tested with UTF-8)
* Support for both %hex and #octal request encodings
* Try to get server hostname from $HOSTNAME or gethostname()
* Basic support for different platforms via HAVE_XX defines
2009-12-30 Kim Holviala <kim@holviala.com>
* Released version 0.1
* Basic rfc1436 functionality works
* Fancy menus with file dates & sizes
* Options via command line (with sensible defaults)
2009-12-28 Kim Holviala <kim@holviala.com>
* Started coding kgopherd
* Trying to remember how "C" works...

113
INSTALL Normal file
View File

@ -0,0 +1,113 @@
Compiling and installing Gophernicus
====================================
Gophernicus requires a C compiler but no extra libraries aside
from standard LIBC ones. Care has been taken to use only
standard POSIX syscalls so that it should work pretty much on
any *nix system. Compiling has only been tested with GCC, but
it will most likely work with others too.
To compile and install run:
$ gzip -cd gophernicus-*.tar.gz | tar xvf -
$ cd gophernicus-*
$ make
$ sudo make install
Then add the below line to your /etc/inetd.conf and restart
inetd. If your system comes with something else than standard
inetd "make install" should have done the right thing already.
gopher stream tcp nowait nobody /usr/sbin/in.gophernicus in.gophernicus -h <hostname>
The -h <hostname> parameter is mandatory for a properly working
Gophernicus. Other parameters can also be added, see the full
list by running "/usr/sbin/in.gophernicus -?"
By default Gophernicus serves gopher documents from /var/gopher
although that can be changed by using the -r <root> parameter.
To enable virtual hosting create hostname directories under
the gopher root and make sure you have at least the primary
hostname (the one set with -h <hostname>) directory available
(mkdir /var/gopher/$HOSTNAME).
Compiling on Debian Linux (and Ubuntu)
======================================
The above commands work on Debian just fine, but if you prefer
having everything installed as packages run "make deb" instead
of plain "make". If all the dependencies were in place you'll
end up with an offical-looking deb package in the parent
directory (don't ask - that's just how it works). And instead
of "sudo make install" you should just install the deb with
"dpkg -i ../gophernicus_*.deb" after which It Should Just
Work(tm).
Compiling on Mac OS X
=====================
When you run "make install" on OSX-like system with launchd
the install routine also installs a plist file and tells launchd
to start the server up. In other words, It Just Works(tm).
Cross-compiling
===============
Cross-compiling to a different target architecture can be done
by defining HOSTCC and CC to be different compilers. HOSTCC
must point to a local arch compiler, and CC to the target
arch one.
$ make HOSTCC=gcc CC=target-arch-gcc
Shared memory issues
====================
Gophernicus uses SYSV shared memory for session tracking and
statistics. It creates the shared memory block using mode 600
and a predefined key which means that a shared memory block
created with one user cannot be used by another user. Simply
said, running in.gophernicus as yourself will allocate that
memory, and then running the binary through inetd as another
user (nobody) will be denied access to that memory.
If that happens you can simply delete the memory block and
let Gophernicus recreate it - no harm done.
$ su -
# ipcs -m | grep beeb
# ipcrm -M <key from the above command>
Porting to different platforms
==============================
If you need to port Gophernicus to a new platform, please take
a look at gophernicus.h which has a bunch of HAVE_* #defines.
Fiddling with those usually makes it possible to compile a working
server. If you succeed in compiling Gophernicus to a new
platform please send the patches to kim@holviala.com so I can
include them into the next release.
Tested (and semi-supported) platforms include:
OS Arch Compiler
+-------------+-------------+-------------+
AIX 5.1 POWER3 gcc 4
AIX 6.1 POWER4 gcc 4
AIX 7.1 POWER5 gcc 4
CentOS 5.5 x86_64 gcc 4
Debian Linux x86_64 gcc 4
Debian Linux armv5tel gcc 4
MacOSX 10.5 i386 gcc 4
MacOSX 10.7 x86_64 llvm-gcc 4
MacOSX 10.8 x86_64 clang 3
NetBSD 5.0 x86_64 gcc 4
Haiku R1 i386 gcc 2

22
LICENSE Normal file
View File

@ -0,0 +1,22 @@
Gophernicus - Copyright (c) 2009-2012 Kim Holviala <kim@holviala.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:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS 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.

248
Makefile Normal file
View File

@ -0,0 +1,248 @@
##
## Gophernicus server Makefile
##
#
# Variables and default configuration
#
NAME = gophernicus
PACKAGE = $(NAME)
BINARY = in.$(NAME)
VERSION = 1.4
SOURCES = $(NAME).c file.c menu.c string.c platform.c session.c options.c
HEADERS = functions.h files.h
OBJECTS = $(SOURCES:.c=.o)
DOCS = LICENSE README INSTALL TODO ChangeLog README.Gophermap gophertag
INSTALL = PATH=$$PATH:/usr/sbin ./install-sh -o 0 -g 0
DESTDIR = /usr
SBINDIR = $(DESTDIR)/sbin
DOCDIR = $(DESTDIR)/share/doc/$(PACKAGE)
ROOT = /var/gopher
OSXROOT = /Library/GopherServer
WRTROOT = /gopher
MAP = gophermap
INETD = /etc/inetd.conf
XINETD = /etc/xinetd.d
LAUNCHD = /Library/LaunchDaemons
PLIST = org.gophernicus.server.plist
NET_SRV = /boot/common/settings/network/services
DIST = $(PACKAGE)-$(VERSION)
TGZ = $(DIST).tar.gz
RELDIR = /var/gopher/gophernicus.org/software/gophernicus/server/
CC = gcc
HOSTCC = $(CC)
CFLAGS = -O2 -Wall
LDFLAGS =
#
# Platform support, compatible with both BSD and GNU make
#
all:
@case `uname` in \
Darwin) $(MAKE) ROOT="$(OSXROOT)" $(BINARY); ;; \
Haiku) $(MAKE) EXTRA_LDFLAGS="-lnetwork" $(BINARY); ;; \
*) $(MAKE) $(BINARY); ;; \
esac
generic: $(BINARY)
#
# Special targets
#
deb:
dpkg-buildpackage -rfakeroot -uc -us
#
# Building
#
$(NAME).c: $(NAME).h $(HEADERS)
$(BINARY): $(OBJECTS)
$(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(OBJECTS) -o $@
.c.o:
$(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) -DVERSION="\"$(VERSION)\"" -DDEFAULT_ROOT="\"$(ROOT)\"" $< -o $@
headers: $(HEADERS)
@echo
functions.h:
echo "/* Automatically generated function definitions */" > $@
echo >> $@
grep -h "^[a-z]" $(SOURCES) | grep -v "int main" | sed -e "s/ =.*$$//" -e "s/ *$$/;/" >> $@
@echo
bin2c: bin2c.c
$(HOSTCC) bin2c.c -o $@
@echo
files.h: bin2c
sed -n -e "1,/^ $$/p" README > README.options
./bin2c -0 -n README README.options > $@
./bin2c -0 LICENSE >> $@
./bin2c -n ERROR_GIF error.gif >> $@
@echo
#
# Cleanup after building
#
clean: clean-build clean-deb
clean-build:
rm -f $(BINARY) $(OBJECTS) $(TGZ) $(HEADERS) README.options bin2c
clean-deb:
if [ -d debian/$(PACKAGE) ]; then fakeroot debian/rules clean; fi
#
# Install targets
#
install:
@case `uname` in \
Darwin) $(MAKE) ROOT="$(OSXROOT)" install-files install-docs install-root install-osx install-done; ;; \
Haiku) $(MAKE) SBINDIR=/boot/common/bin DOCDIR=/boot/common/share/doc/$(PACKAGE) \
install-files install-docs install-root install-haiku install-done; ;; \
*) $(MAKE) install-files install-docs install-root; ;; \
esac
@if [ -d "$(XINETD)" ]; then $(MAKE) install-xinetd install-done; fi
@if [ -f "$(INETD)" ]; then $(MAKE) install-inetd; fi
.PHONY: install
install-done:
@echo
@echo "======================================================================"
@echo
@echo "Gophernicus has now been succesfully installed. To try it out, launch"
@echo "your favorite gopher browser and navigate to this URL:"
@echo
@echo " gopher://`hostname`/"
@echo
@echo "======================================================================"
@echo
install-files:
mkdir -p $(SBINDIR)
$(INSTALL) -s -m 755 $(BINARY) $(SBINDIR)
@echo
install-docs:
mkdir -p $(DOCDIR)
$(INSTALL) -m 644 $(DOCS) $(DOCDIR)
@echo
install-root:
if [ ! -d "$(ROOT)" ]; then \
mkdir -p $(ROOT); \
$(INSTALL) -m 644 $(MAP) $(ROOT); \
ln -s $(DOCDIR) $(ROOT)/docs; \
fi
@echo
install-inetd:
@echo
@echo "======================================================================"
@echo
@echo "Looks like your system has the traditional internet superserver inetd."
@echo "Automatic installations aren't supported, so please add the following"
@echo "line to the end of your /etc/inetd.conf and restart or kill -HUP the"
@echo "inetd process."
@echo
@echo "gopher stream tcp nowait nobody $(SBINDIR)/$(BINARY) $(BINARY) -h `hostname`"
@echo
@echo "======================================================================"
@echo
install-xinetd:
if [ -d "$(XINETD)" -a ! -f "$(XINETD)/$(NAME)" ]; then \
sed -e "s/@HOSTNAME@/`hostname`/g" $(NAME).xinetd > $(XINETD)/$(NAME); \
[ -x /sbin/service ] && /sbin/service xinetd reload; \
fi
@echo
install-osx:
if [ -d "$(LAUNCHD)" -a ! -f "$(LAUNCHD)/$(PLIST)" ]; then \
sed -e "s/@HOSTNAME@/`hostname`/g" org.gophernicus.server.plist > \
$(LAUNCHD)/$(PLIST); \
launchctl load $(LAUNCHD)/$(PLIST); \
fi
@echo
chown -h root:admin $(ROOT) $(ROOT)/*
chmod -h 0775 $(ROOT) $(ROOT)/docs
@echo
install-haiku:
if [ -f "$(NET_SRV)" -a ! "`grep -m1 gopher $(NET_SRV)`" ]; then \
(echo ""; \
echo "service gopher {"; \
echo " family inet"; \
echo " protocol tcp"; \
echo " port 70"; \
echo " launch in.gophernicus -h `hostname`"; \
echo "}") >> $(NET_SRV); \
fi
@echo
chown user:root $(DOCDIR)/* $(SBINDIR)/$(BINARY) $(ROOT)/$(MAP)
@echo
ps | grep net_server | grep -v grep | awk '{ print $$2 }' | xargs kill
nohup /boot/system/servers/net_server >/dev/null 2>/dev/null &
@echo
#
# Uninstall targets
#
uninstall: uninstall-xinetd uninstall-launchd
rm -f $(SBINDIR)/$(BINARY)
for DOC in $(DOCS); do rm -f $(DOCDIR)/$$DOC; done
rmdir -p $(SBINDIR) $(DOCDIR) 2>/dev/null || true
@echo
uninstall-xinetd:
if grep -q $(BINARY) "$(XINETD)/gopher" 2>/dev/null; then \
rm -f $(XINETD)/gopher; \
[ -x /sbin/service ] && service xinetd reload; \
fi
@echo
uninstall-launchd:
if [ -f $(LAUNCHD)/$(PLIST) ]; then \
launchctl unload $(LAUNCHD)/$(PLIST); \
rm -f $(LAUNCHD)/$(PLIST); \
fi
if [ -L $(ROOT) ]; then \
rm -f $(ROOT); \
fi
@echo
#
# Release targets
#
dist: clean functions.h
mkdir -p /tmp/$(DIST)
tar -cf - ./ | (cd /tmp/$(DIST) && tar -xf -)
(cd /tmp/ && tar -cvf - $(DIST)) | gzip > $(TGZ)
rm -rf /tmp/$(DIST)
release: dist
cp $(TGZ) $(RELDIR)
#
# List all C defines
#
defines:
$(CC) -dM -E $(NAME).c

237
README Normal file
View File

@ -0,0 +1,237 @@
Gophernicus - Copyright (c) 2009-2012 Kim Holviala <kim@holviala.com>
Gophernicus is a modern full-featured (and hopefully) secure gopher
daemon for inetd. It is licensed under the BSD license.
Command line options:
-h hostname Change server hostname (FQDN) [$HOSTNAME]
-p port Change server port [70]
-r root Change gopher root [/var/gopher]
-t type Change default gopher filetype [0]
-g mapfile Change gophermap file [gophermap]
-a tagfile Change gophertag file [gophertag]
-c cgidir Change CGI script directory [/cgi-bin/]
-u userdir Change users personal gopherspace [public_gopher]
-l logfile Log to Apache-compatible combined format logfile
-w width Change default page width [70]
-o charset Change default output charset [US-ASCII]
-s seconds Session timeout in seconds [1800]
-i hits Maximum hits until throttling [4096]
-k kbytes Maximum transfer until throttling [4194304]
-f filterdir Specify directory for output filters
-e ext=type Map file extension to gopher filetype
-R old=new Rewrite the beginning of a selector
-D text|file Set or load server description for caps.txt
-L text|file Set or load server location for caps.txt
-A admin Set admin email for caps.txt
-nv Disable virtual hosting
-nl Disable parent directory links
-nh Disable menu header (title)
-nf Disable menu footer
-nd Disable dates and filesizes in menus
-nc Disable file content detection
-no Disable charset conversion for output
-nq Disable HTTP-style query strings (?query)
-ns Disable logging to syslog
-na Disable autogenerated caps.txt
-nm Disable shared memory use (for debugging)
-nr Disable root user checking (for debugging)
-d Debug to syslog (not for production use)
-b Display the BSD license
-? Display this help
Setting up a gopher site
========================
After succesfully installing Gophernicus (see INSTALL) you need to set
up the gopher root directory. By default Gophernicus serves documents
from /var/gopher so start by creating that directory and making sure
it's world-readable. Then, simply add files and directories under your
root, fire up a gopher browser (Firefox, Lynx) and open up this URL:
gopher://<HOSTNAME>/ (where <HOSTNAME> is your servers hostname)
That's it, your first gopher site is now up and running. If the links
on the root menu don't work, make sure you are using the -h <HOSTNAME>
parameter in your inetd.conf (with a valid resolveable hostname
instead of <HOSTNAME> - see INSTALL).
Security
========
Gophernicus has been written with high security in mind. There should
be no buffer overflows or memory allocation problems so it should be
safe to run a publicly available gopher server with Gophernicus.
However, the security settings (which are non-changeable) are so strict
that you need to keep one thing in mind. Gophernicus will only serve
world-readable content. Being readable by the server process is not
enough, all files and directories MUST be world-readable or they are
simply hidden from all listings and denied if a client asks for them.
Gophermaps
==========
By default all gopher menus are automatically generated from the
content of the directory being viewed. If you want to have
informational text along with the files, or if you want to completely
replace the generated menu with your own you need to take a look at
gophermaps. See the file README.gophermap for more information.
Gophertags
==========
A gophertag file can be used to virtually rename a directory. Let's
assume that you have a directory called "foo" somewhere - it will
be listed as "foo" in all automatically generated menus. Now if you
create a file foo/gophertag and put the text "bar" into it the menus
will show "bar" but the links will still point to "foo". This is
useful for creating descriptive names for directories without
littering the file system with spaces and weird characters.
Personal gopherspaces
=====================
Gophernicus supports users personal gopherspaces. If a user has
world-readable directory called public_gopher/ under his home, a
request for gopher://<HOSTNAME>/1/~user/ will serve documents from
that directory.
Virtual hosting
===============
Gophernicus supports virtual hosting, or serving more than one logical
domain using the same IP address. Since gopher (RFC1436) doesn't
support virtual hosting this requires some clever (but mostly invisble)
hacks.
To enable virtual hosting create one or more directories under your
gopher root which are named after your domain names. The primary vhost
directory (set with the -h <HOSTNAME> option) must exist or virtual
hosting will be disabled. Then simply add content to the hostname
directories and you're up and running.
Almost.
To make gopher clients work properly with virtual hosting, create a
root gophermap for each of your domains and include the "%" type
character to create a list of all available virtual hosts (see
README.gophermap). The generated virtual host links will be created so
that standard gopher clients will find the correct domain even when
they don't specifically tell the server which host they're trying to
reach.
CGI support
===========
Gophernicus supports most parts of the CGI/1.1 standard. Most standard
CGI variables are set, and some non-standard ones are added.
By default all scripts and binaries under any directory called
/cgi-bin/ are executed as CGI scripts (this includes cgi-bin
directories under users personal gopherspaces). Also, if a gophermap
is marked executable it is also processed as an CGI script.
As with regular files, CGI scripts must be world-executable (and
readable) or they will be ignored. Make sure your CGI script is safe
with ANY user input as poorly coded CGI scripts are the number #1
security problem with publicly open *nix servers.
Output filtering and PHP support
================================
In addition to CGI scripts Gophernicus supports output filtering
scripts. By default output filtering is turned off, but you can turn
it on by using the -f <FILTERDIR> option, creating that directory
and creating one or more scripts in there named by either the file
suffix, or by the gopher filetype char.
If a file is to be served out which matches either the file suffix
script, or the filetype script then instead of simply sending the
file to client the output filter script is executed with the
original file as the first parameter and the output of the script
is then sent to client.
For PHP support install the CLI version of the PHP interpreter and
then symlink (or copy) that binary to the directory specified with
-f option using the destination name "php".
$ ln -s /usr/bin/php5-cli /usr/lib/gophernicus/filters/php
After that all files with the php suffix will be "filtered" through
the PHP command line interpreter. In other words, PHP starts working.
And don't use the CGI version of PHP as it outputs HTTP headers the
gopher protocol doesn't have.
Charset support and conversions
===============================
Gophernicus supports three charsets: US-ASCII, ISO-8859-1 and UTF-8.
All textual input is internally upconverted to UTF-8 and then
downconverted to whatever charset the client is asking for. The
conversion is input autosensing which means that you don't have to
specify your filesystem charset, or the charset of your text files -
it's all detected automatically.
With standard gopher clients this is a bit of a problem as your text
files WILL be converted to 7-bit US-ASCII. This means that all 8-bit
charaters WILL BE LOST. This decision was made because no gopher
client that I tested was reliably cabable of decoding anything else
than pure US-ASCII. If you want to disable the conversion use the
"-no" option, or if you'd like to change the default output charset to
something else than US-ASCII just use for example the "-o ISO-8859-1"
option.
Selector rewriting
==================
Selector rewriting lets you rewrite parts of the selector on the fly.
Well, not parts, but really just the start of it. And the rewrite
enging here is nothing like Apache's mod_rewrite as I was too lazy
to integrate any regex libraries... So, all it does is rewrite a
fixed string at the start of the selector to something else. This
will let you move your directories around while making sure that
existing deeplinks still work.
Examples:
-R "/~user=/~luser"
-R "/old-dir=/new-dir"
Session tracking and statistics
===============================
To enable virtual hosting with gopher (RFC1436) clients Gophernicus
tracks users and their session. As a side effect of that session
tracking, Gophernicus has simple throttling controls to keep nasty
users from killing your precious 120MHz PPC 604e server from dying
under the load. The throttling defaults are high enough that normal
human users will never hit the limits, but it's possible (and mostly
preferrable) that a badly behaving crawling agent will be throttled.
The current sessions and other real-time status data can be viewed
by opening the URL gopher://<HOSTNAME>/0/server-status . This status
view has been modeled after the Apache server-status which means
that it's possible to integrate Gophernicus into existing server
monitoring systems. To ease up such integrations, Gophernicus
supports HTTP requests of the server-status page using an URL like
http://<HOSTNAME>:70/server-status?auto

109
README.Gophermap Normal file
View File

@ -0,0 +1,109 @@
!Sample gophermap for Gophernicus
##
## This is a sample gophermap.
##
#
Creating a file called "gophermap" into a directory disables the
normal resource listing and replaces it with the contents of the map
file. You can also have inline gophermaps - files with a ".gophermap"
extension are parsed as gophermaps and displayed in between normal
resources in alphabetical order.
In a gophermap any line that doesn't contain a <TAB> character is
automatically converted to an type "i" gopher resource which are
displayed as plain text in the client. Lines which contain tabs are
intepreted as gopher resource lines which the client will render as
links. The first line of a gophermap should be a !Title line
describing the menu.
Dynamic gophermaps are possible by making the gophermap a script and
marking it as executable. All script output is parsed just like a
static gophermap, for example lines without tabs are converted to "i"
resources. Executable gophermaps are always ran through the default
shell (/bin/sh) so depending on your operating system that's either
slow, or really unbearably slow...
The format of a gophermap resource line is simple:
Xname<TAB>selector<TAB>host<TAB>port
Where:
X is the gopher filetype
name is an explanation of the resource
selector is the path to resource
host:port are the hostname and port number to go to
Type and name are mandatory. If you don't specify a selector, the
name field will be also used as the selector. If you don't specify
host or port the host:port of the current server are used instead.
Also make sure to use ONLY ONE TAB between the fields.
Valid filetypes include:
0 text file
1 directory
3 error message
5 archive file (zip, tar etc)
7 search query
8 telnet session
9 binary file
g GIF image
h HTML file
i info text
I generic image file (other than GIF)
d document file (ps, pdf, doc etc)
s sound file
; video file
c calendar file
M MIME file (mbox, emails etc)
Additional type characters supported by Gophernicus:
# comment - rest of the line is ignored
!title menu title (use on the first line)
-file hide the file from listings
:ext=type change filetype (for this directory only)
~ include a list of users with valid ~/public_gopher
% include a list of available virtual hosts
=mapfile include or execute other gophermap
* stop processing gophermap, include file listing
. stop processing gophermap (default)
Examples of valid resource lines:
1subdir
1Relative internal link subdir
1Absolute internal link /subdir
1External link / gopher.floodgap.com 70
1External relative link (which shouldn't work) subdir/ gopher.domain.dom 70
0Finger-to-gopher link kim holviala.com 79
hLink to a website URL:http://www.google.com/
hLink to a local html page /path/to/file.html
5Link to an tar archive /path/to/archive.tar.gz
9Link to a binary file /path/to/binary
7Search engine query /query
8Telnet session kim holviala.com 79
# Hide a few files from the menu listing generated by *
-hiddenfile.txt
-hiddendir
# Change filetypes for this directory
:png=g
:foo=b
Include links to users own gopherspaces:
~
List all available virtual hosts:
%
Include sub-gophermap:
=LICENSE
Execute script and parse output as subgophermap:
=/usr/bin/uptime
Here we stop processing the gophermap and include the regular menu:
*

10
TODO Normal file
View File

@ -0,0 +1,10 @@
Things I might work on:
* Fix vhost part of README
* Support for config files
* Standalone pre-forked (threaded?) version
* Password-protected resources
* Allow/Deny per IP/host
* Automated feature testing script
* SSL/TLS

67
bin2c.c Executable file
View File

@ -0,0 +1,67 @@
/*
* Convert any file into a C #define
*
* Yes, this would have been a perl one-liner, but I didn't want
* to include compile-time dependency for perl...
*/
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
FILE *fp;
char *source = NULL;
char *name = NULL;
int first = 1;
int zero = 0;
int c;
int i;
/* Parse args */
while ((c = getopt(argc, argv, "n:0")) != -1) {
switch(c) {
case 'n': name = optarg; break;
case '0': zero = 1; break;
}
}
source = argv[optind];
if (!name) name = source;
/* Check args */
if (!source) {
fprintf(stderr, "Usage: %s [-0] [-n <name>] <source>\n", argv[0]);
return 1;
}
/* Try to open the source file */
if ((fp = fopen(source, "r")) == NULL) {
perror("Couldn't open source file");
return 1;
}
/* Convert */
printf("/* Automatically generated from %s */\n\n"
"#define %s { \\\n", source, name);
do {
for (i = 0; i < 16; i++) {
if ((c = fgetc(fp)) == EOF) {
if (zero--) c = '\0';
else break;
}
if (i == 0 && !first) printf(", \\\n");
if (i > 0) printf(", ");
printf("0x%02x", c);
first = 0;
}
} while (c != EOF);
printf("}\n\n");
fclose(fp);
return 0;
}

37
debian/changelog vendored Normal file
View File

@ -0,0 +1,37 @@
gophernicus (1.4) unstable; urgency=low
* New upstream release
-- Kim Holviala <kim@holviala.com> Sun, 02 Dec 2012 09:54:55 +0200
gophernicus (1.3) unstable; urgency=low
* New upstream release
* Fixed one off-by-one
-- Kim Holviala <kim@holviala.com> Tue, 12 Jun 2012 13:07:46 +0300
gophernicus (1.2) unstable; urgency=low
* New upstream release
-- Kim Holviala <kim@holviala.com> Fri, 04 May 2012 22:05:01 +0300
gophernicus (1.1) unstable; urgency=low
* New upstream release
* Security update, so upgrading is recommended
-- Kim Holviala <kim@holviala.com> Sat, 16 Oct 2010 08:54:13 +0300
gophernicus (1.0) unstable; urgency=low
* Initial debianized release
* File logging by default, installs logrotate config
* Pre-configures php support but only suggests php5-cli
* Create a default gopher root
* Installs an @reboot cron entry to snoop system type
using a dmidecode script (which must be run as root)
-- Kim Holviala <kim@holviala.com> Mon, 27 Sep 2010 08:11:12 +0300

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
5

16
debian/control vendored Normal file
View File

@ -0,0 +1,16 @@
Source: gophernicus
Section: net
Priority: extra
Maintainer: Kim Holviala <kim@holviala.com>
Build-Depends: debhelper (>= 5)
Standards-Version: 3.7.3
Homepage: gopher://gophernicus.org/1/software/gophernicus/server/
Package: gophernicus
Architecture: any
Depends: ${shlibs:Depends}, debconf, netbase, openbsd-inetd | inet-superserver
Recommends: lsb-release
Suggests: lynx, php5-cli
Description: Modern full-featured gopher server for inetd
Gophernicus is a modern full-featured (and hopefully) secure
gopher daemon for inetd.

22
debian/copyright vendored Normal file
View File

@ -0,0 +1,22 @@
Gophernicus - Copyright (c) 2009-2010 Kim Holviala <kim@holviala.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:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS 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.

4
debian/dirs vendored Normal file
View File

@ -0,0 +1,4 @@
usr/sbin
var/gopher
var/log/gophernicus
usr/lib/gophernicus/filters

5
debian/docs vendored Normal file
View File

@ -0,0 +1,5 @@
README
README.Gophermap
TODO
INSTALL
gophertag

14
debian/gophernicus.config vendored Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
# Source debconf library
. /usr/share/debconf/confmodule
# Ask for a hostname
db_input high gophernicus/fqdn || true
db_go
# Clear old config on reconfigure
if [ "$1" = "reconfigure" ]; then
update-inetd --remove "#<off># gopher"
fi

View File

@ -0,0 +1,3 @@
^\w{3} [ :0-9]{11} [._[:alnum:]-]+ in.gophernicus\[[0-9]+\]: request for "[^"]*" from [._[:alnum:]:-]+$
^\w{3} [ :0-9]{11} [._[:alnum:]-]+ in.gophernicus\[[0-9]+\]: error "No such file or directory" for request "[^"]*" from [._[:alnum:]:-]+$
^\w{3} [ :0-9]{11} [._[:alnum:]-]+ in.gophernicus\[[0-9]+\]: error "User not found" for request "/~[^"]*" from [._[:alnum:]:-]+$

7
debian/gophernicus.logrotate vendored Normal file
View File

@ -0,0 +1,7 @@
/var/log/gophernicus/server.log {
rotate 6
weekly
compress
missingok
notifempty
}

4
debian/gophernicus.templates vendored Normal file
View File

@ -0,0 +1,4 @@
Template: gophernicus/fqdn
Type: string
Default:
Description: Fully-qualified hostname for the gopher server:

37
debian/postinst vendored Normal file
View File

@ -0,0 +1,37 @@
#!/bin/sh
#DEBHELPER#
# Source debconf library.
. /usr/share/debconf/confmodule
# Configuration
HOSTNAME="`hostname`"
ROOT=/var/gopher
PACKAGE=gophernicus
LOGDIR=/var/log/$PACKAGE
LIBDIR=/usr/lib/$PACKAGE
BINARY=in.gophernicus
USER=nobody
# Get hostname from debconf
db_get gophernicus/fqdn
if [ "$RET" ]; then
HOSTNAME="`echo $RET | tr -cd 'A-Za-z0-9.-'`"
fi
# Generate inetd service
SERVICE="gopher\t\tstream\ttcp\tnowait\t$USER\t/usr/sbin/$BINARY\t$BINARY -h $HOSTNAME -l $LOGDIR/server.log -f /usr/lib/$PACKAGE/filters"
# Configure gophernicus
if [ "$1" = "configure" ]; then
if [ ! -f "$ROOT/gophermap" ]; then
cp $LIBDIR/gophermap $ROOT/
fi
chown $USER.adm $LOGDIR
chmod 0750 $LOGDIR
update-inetd --add "$SERVICE"
fi

8
debian/postrm vendored Normal file
View File

@ -0,0 +1,8 @@
#!/bin/sh
if [ "$1" = "purge" ]; then
update-inetd --remove "#<off># gopher"
fi
#DEBHELPER#

6
debian/prerm vendored Normal file
View File

@ -0,0 +1,6 @@
#!/bin/sh
update-inetd --disable gopher
#DEBHELPER#

85
debian/rules vendored Executable file
View File

@ -0,0 +1,85 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Gophernicus debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# Installation directory
DEST=$(CURDIR)/debian/gophernicus
configure:
build: build-stamp
build-stamp:
dh_testdir
$(MAKE)
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp
$(MAKE) clean-build
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/gophernicus
$(MAKE) DESTDIR=$(DEST)/usr install-files
rm -rf $(DEST)/tmp
ln -s /usr/share/doc/gophernicus/ $(DEST)/var/gopher/docs
ln -s /usr/bin/php5 $(DEST)/usr/lib/gophernicus/filters/php
cp gophermap $(DEST)/usr/lib/gophernicus/
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
# dh_installexamples
# dh_install
# dh_installmenu
dh_installdebconf
dh_installlogrotate
dh_installlogcheck
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
# dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

BIN
error.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

25
examples/counter/counter.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/sh
##
## A simple visitor counter to use with gophermaps
##
## Usage: counter.sh <pre message> <post message>
##
# Figure out a safe file to keep our counter
HASH=`echo "$SELECTOR" | md5sum | cut -d" " -f1`
FILE=/var/tmp/gopher-counter-$HASH
# Get count and the previous visitors IP address
COUNT="`cut -d' ' -f1 $FILE`"
OLD_ADDR="`cut -d' ' -f2 $FILE`"
# Increase counter only if the user is new
if [ "$OLD_ADDR" != "$REMOTE_ADDR" ]; then
COUNT=$(( COUNT + 1 ))
echo "$COUNT $REMOTE_ADDR" > $FILE
fi
# Output counter message
echo "$1$COUNT$2"

402
file.c Normal file
View File

@ -0,0 +1,402 @@
/*
* Gophernicus - Copyright (c) 2009-2012 Kim Holviala <kim@holviala.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:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS 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 "gophernicus.h"
/*
* Send a binary file to the client
*/
void send_binary_file(state *st)
{
/* Faster sendfile() version */
#ifdef HAVE_SENDFILE
int fd;
off_t offset = 0;
if (st->debug) syslog(LOG_INFO, "outputting binary file \"%s\"", st->req_realpath);
if ((fd = open(st->req_realpath, O_RDONLY)) == ERROR) return;
sendfile(1, fd, &offset, st->req_filesize);
close(fd);
/* More compatible POSIX fread()/fwrite() version */
#else
FILE *fp;
char buf[BUFSIZE];
int bytes;
if (st->debug) syslog(LOG_INFO, "outputting binary file \"%s\"", st->req_realpath);
if ((fp = fopen(st->req_realpath , "r")) == NULL) return;
while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
fwrite(buf, bytes, 1, stdout);
fclose(fp);
#endif
}
/*
* Send a text file to the client
*/
void send_text_file(state *st)
{
FILE *fp;
char in[BUFSIZE];
char out[BUFSIZE];
int line;
if (st->debug) syslog(LOG_INFO, "outputting text file \"%s\"", st->req_realpath);
if ((fp = fopen(st->req_realpath , "r")) == NULL) return;
/* Loop through the file line by line */
line = 0;
while (fgets(in, sizeof(in), fp)) {
/* Covert to output charset & print */
if (st->opt_iconv) sstrniconv(st->out_charset, out, in);
else sstrlcpy(out, in);
chomp(out);
#ifdef ENABLE_STRICT_RFC1436
if (strcmp(out, ".") == MATCH) printf(".." CRLF);
else
#endif
printf("%s" CRLF, out);
line++;
}
#ifdef ENABLE_STRICT_RFC1436
printf("." CRLF);
#endif
fclose(fp);
}
/*
* Print hURL redirect page
*/
void url_redirect(state *st)
{
char dest[BUFSIZE];
char *c;
/* Basic security checking */
sstrlcpy(dest, st->req_selector + 4);
if (sstrncmp(dest, "http://") != MATCH &&
sstrncmp(dest, "ftp://") != MATCH &&
sstrncmp(dest, "mailto:") != MATCH)
die(st, ERR_ACCESS, "Refusing to HTTP redirect unsafe protocols");
if ((c = strchr(dest, '"'))) *c = '\0';
if ((c = strchr(dest, '?'))) *c = '\0';
/* Log the redirect */
if (st->opt_syslog) {
syslog(LOG_INFO, "request for \"gopher://%s:%i/h%s\" from %s",
st->server_host,
st->server_port,
st->req_selector,
st->req_remote_addr);
}
log_combined(st, HTTP_OK);
/* Output HTML */
printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
"<HTML>\n<HEAD>\n"
" <META HTTP-EQUIV=\"Refresh\" content=\"1;URL=%1$s\">\n"
" <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;charset=iso-8859-1\">\n"
" <TITLE>URL Redirect page</TITLE>\n"
"</HEAD>\n<BODY>\n"
"<STRONG>Redirecting to <A HREF=\"%1$s\">%1$s</A></STRONG>\n"
"<PRE>\n", dest);
footer(st);
printf("</PRE>\n</BODY>\n</HTML>\n");
}
/*
* Handle /server-status
*/
#ifdef HAVE_SHMEM
void server_status(state *st, shm_state *shm, int shmid)
{
struct shmid_ds shm_ds;
time_t now;
time_t uptime;
int sessions;
int i;
/* Log the request */
if (st->opt_syslog) {
syslog(LOG_INFO, "request for \"gopher://%s:%i/0" SERVER_STATUS "\" from %s",
st->server_host,
st->server_port,
st->req_remote_addr);
}
log_combined(st, HTTP_OK);
/* Quit if shared memory isn't initialized yet */
if (!shm) return;
/* Update counters */
shm->hits++;
shm->kbytes += 1;
/* Get server uptime */
now = time(NULL);
uptime = (now - shm->start_time) + 1;
/* Get shared memory info */
shmctl(shmid, IPC_STAT, &shm_ds);
/* Print statistics */
printf("Total Accesses: %li" CRLF
"Total kBytes: %li" CRLF
"Uptime: %i" CRLF
"ReqPerSec: %.3f" CRLF
"BytesPerSec: %li" CRLF
"BytesPerReq: %li" CRLF
"BusyServers: %i" CRLF
"IdleServers: 0" CRLF
"CPULoad: %.2f" CRLF,
shm->hits,
shm->kbytes,
(int) uptime,
(float) shm->hits / (float) uptime,
shm->kbytes * 1024 / (int) uptime,
shm->kbytes * 1024 / (shm->hits + 1),
(int) shm_ds.shm_nattch,
loadavg());
/* Print active sessions */
sessions = 0;
for (i = 0; i < SHM_SESSIONS; i++) {
if ((now - shm->session[i].req_atime) < st->session_timeout) {
sessions++;
printf("Session: %-4i %-40s %-4li %-7li gopher://%s:%i/%c%s" CRLF,
(int) (now - shm->session[i].req_atime),
shm->session[i].req_remote_addr,
shm->session[i].hits,
shm->session[i].kbytes,
shm->session[i].server_host,
shm->session[i].server_port,
shm->session[i].req_filetype,
shm->session[i].req_selector);
}
}
printf("Total Sessions: %i" CRLF, sessions);
}
#endif
/*
* Handle /caps.txt
*/
void caps_txt(state *st, shm_state *shm)
{
/* Log the request */
if (st->opt_syslog) {
syslog(LOG_INFO, "request for \"gopher://%s:%i/0" CAPS_TXT "\" from %s",
st->server_host,
st->server_port,
st->req_remote_addr);
}
log_combined(st, HTTP_OK);
/* Update counters */
#ifdef HAVE_SHMEM
if (shm) {
shm->hits++;
shm->kbytes += 1;
/* Update session data */
st->req_filesize += 1024;
update_shm_session(st, shm);
}
#endif
/* Standard caps.txt stuff */
printf("CAPS" CRLF
CRLF
"##" CRLF
"## This is an automatically generated caps file." CRLF
"##" CRLF
CRLF
"CapsVersion=1" CRLF
"ExpireCapsAfter=%i" CRLF
CRLF
"PathDelimeter=/" CRLF
"PathIdentity=." CRLF
"PathParent=.." CRLF
"PathParentDouble=FALSE" CRLF
"PathKeepPreDelimeter=FALSE" CRLF
CRLF
"ServerSoftware=" SERVER_SOFTWARE CRLF
"ServerSoftwareVersion=" VERSION CRLF
"ServerArchitecture=%s" CRLF,
st->session_timeout,
st->server_platform);
/* Optional keys */
if (*st->server_description)
printf("ServerDescription=%s" CRLF, st->server_description);
if (*st->server_location)
printf("ServerGeolocationString=%s" CRLF, st->server_location);
if (*st->server_admin)
printf("ServerAdmin=%s" CRLF, st->server_admin);
}
/*
* Setup environment variables as per the CGI spec
*/
void setenv_cgi(state *st, char *script)
{
char buf[BUFSIZE];
/* Security */
setenv("PATH", SAFE_PATH, 1);