summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorpst <pst@FreeBSD.org>1997-02-06 17:52:29 +0000
committerpst <pst@FreeBSD.org>1997-02-06 17:52:29 +0000
commit2dfcbf193123fd16b26454eeffa4bbd014e52c53 (patch)
treeec9d150c9da4390c2d223a04ac002523cbfd7f36 /contrib
downloadFreeBSD-src-2dfcbf193123fd16b26454eeffa4bbd014e52c53.zip
FreeBSD-src-2dfcbf193123fd16b26454eeffa4bbd014e52c53.tar.gz
Initial import of OPIE v2.3 from
ftp://ftp.nrl.navy.mil/pub/security/opie/
Diffstat (limited to 'contrib')
-rw-r--r--contrib/opie/BUG-REPORT81
-rw-r--r--contrib/opie/COPYRIGHT.NRL68
-rw-r--r--contrib/opie/INSTALL88
-rw-r--r--contrib/opie/License.TIN45
-rw-r--r--contrib/opie/Makefile.in271
-rw-r--r--contrib/opie/README391
-rw-r--r--contrib/opie/acconfig.h118
-rw-r--r--contrib/opie/config.h.in324
-rw-r--r--contrib/opie/config.testeflag12
-rwxr-xr-xcontrib/opie/configure4089
-rw-r--r--contrib/opie/configure.in455
-rw-r--r--contrib/opie/configure.munger.in16
-rw-r--r--contrib/opie/ftpcmd.y1286
-rw-r--r--contrib/opie/glob.c667
-rw-r--r--contrib/opie/install-sh238
-rw-r--r--contrib/opie/libmissing/Makefile.in30
-rw-r--r--contrib/opie/libmissing/alloca.c494
-rw-r--r--contrib/opie/libmissing/bogus.c1
-rw-r--r--contrib/opie/libmissing/endutent.c18
-rw-r--r--contrib/opie/libmissing/env.c141
-rw-r--r--contrib/opie/libmissing/getcwd.c23
-rw-r--r--contrib/opie/libmissing/getusershell.c67
-rw-r--r--contrib/opie/libmissing/getutline.c50
-rw-r--r--contrib/opie/libmissing/initgroups.c129
-rw-r--r--contrib/opie/libmissing/memcmp.c25
-rw-r--r--contrib/opie/libmissing/memcpy.c25
-rw-r--r--contrib/opie/libmissing/memset.c21
-rw-r--r--contrib/opie/libmissing/pututline.c56
-rw-r--r--contrib/opie/libmissing/sigaddset.c36
-rw-r--r--contrib/opie/libmissing/sigemptyset.c23
-rw-r--r--contrib/opie/libmissing/sigprocmask.c68
-rw-r--r--contrib/opie/libmissing/strchr.c24
-rw-r--r--contrib/opie/libmissing/strerror.c34
-rw-r--r--contrib/opie/libmissing/strncasecmp.c30
-rw-r--r--contrib/opie/libmissing/strrchr.c25
-rw-r--r--contrib/opie/libmissing/sysconf.c30
-rw-r--r--contrib/opie/libmissing/uname.c42
-rw-r--r--contrib/opie/libopie/Makefile.in28
-rw-r--r--contrib/opie/libopie/accessfile.c165
-rw-r--r--contrib/opie/libopie/atob8.c74
-rw-r--r--contrib/opie/libopie/btoa8.c32
-rw-r--r--contrib/opie/libopie/btoe.c2266
-rw-r--r--contrib/opie/libopie/btoh.c35
-rw-r--r--contrib/opie/libopie/challenge.c74
-rw-r--r--contrib/opie/libopie/generator.c110
-rw-r--r--contrib/opie/libopie/getsequence.c27
-rw-r--r--contrib/opie/libopie/getutmpentry.c72
-rw-r--r--contrib/opie/libopie/hash.c52
-rw-r--r--contrib/opie/libopie/hashlen.c51
-rw-r--r--contrib/opie/libopie/insecure.c146
-rw-r--r--contrib/opie/libopie/keycrunch.c64
-rw-r--r--contrib/opie/libopie/lock.c175
-rw-r--r--contrib/opie/libopie/login.c130
-rw-r--r--contrib/opie/libopie/lookup.c30
-rw-r--r--contrib/opie/libopie/md4c.c267
-rw-r--r--contrib/opie/libopie/md5c.c304
-rw-r--r--contrib/opie/libopie/newseed.c99
-rw-r--r--contrib/opie/libopie/open.c61
-rw-r--r--contrib/opie/libopie/parsechallenge.c70
-rw-r--r--contrib/opie/libopie/passcheck.c50
-rw-r--r--contrib/opie/libopie/passwd.c74
-rw-r--r--contrib/opie/libopie/randomchallenge.c43
-rw-r--r--contrib/opie/libopie/readpass.c304
-rw-r--r--contrib/opie/libopie/readrec.c218
-rw-r--r--contrib/opie/libopie/unlock.c103
-rw-r--r--contrib/opie/libopie/verify.c255
-rw-r--r--contrib/opie/libopie/version.c27
-rw-r--r--contrib/opie/libopie/writerec.c85
-rw-r--r--contrib/opie/logwtmp.c154
-rw-r--r--contrib/opie/opie.4346
-rw-r--r--contrib/opie/opie.h224
-rw-r--r--contrib/opie/opie_cfg.h167
-rw-r--r--contrib/opie/opieaccess.587
-rw-r--r--contrib/opie/opieftpd.8280
-rw-r--r--contrib/opie/opieftpd.c1643
-rw-r--r--contrib/opie/opiegen.188
-rw-r--r--contrib/opie/opiegen.c88
-rw-r--r--contrib/opie/opieinfo.199
-rw-r--r--contrib/opie/opieinfo.c90
-rw-r--r--contrib/opie/opiekey.1173
-rw-r--r--contrib/opie/opiekey.c375
-rw-r--r--contrib/opie/opiekeys.566
-rw-r--r--contrib/opie/opielogin.1131
-rw-r--r--contrib/opie/opielogin.c1428
-rw-r--r--contrib/opie/opiepasswd.1176
-rw-r--r--contrib/opie/opiepasswd.c429
-rw-r--r--contrib/opie/opieserv.182
-rw-r--r--contrib/opie/opieserv.c83
-rw-r--r--contrib/opie/opiesu.1101
-rw-r--r--contrib/opie/opiesu.c448
-rw-r--r--contrib/opie/opietest.c255
-rw-r--r--contrib/opie/options.h85
-rw-r--r--contrib/opie/permsfile.c163
-rw-r--r--contrib/opie/popen.c204
94 files changed, 22497 insertions, 0 deletions
diff --git a/contrib/opie/BUG-REPORT b/contrib/opie/BUG-REPORT
new file mode 100644
index 0000000..813b388
--- /dev/null
+++ b/contrib/opie/BUG-REPORT
@@ -0,0 +1,81 @@
+OPIE Software Distribution, Release 2.3 Bug Reporting Form
+======================================= ==================
+
+ Please make a copy of this file and then edit it with your favorite
+text editor to include the answers to the following questions:
+
+1. Your name and electronic mail address, in case we need more information.
+ If you can provide multiple addresses, please do so in case we
+ are unable to reply to the first one.
+
+2. Your exact operating system vendor, name, and version number.
+ Please be more specific than "UNIX" -- most vendors have a name
+ for their particular flavor of UNIX.
+
+3. The exact hardware the system was installed upon.
+
+4. Which compiler and C runtime you used and its version number.
+ For instance, some systems have been known to have the GNU libc
+ installed as well as its native one, or to have a "BSD
+ compatibility" environment.
+
+5. What version of OPIE you are using (the output of opiepasswd -v) and,
+ if you used the Autoconf install, a copy of the config.h, config.log,
+ and Makefile that Autoconf created.
+
+6. A clear description of what you did and what bug then appeared.
+ If your system has the script(1) command, please run a session
+ under that to demonstrate the bug. Window-system cut-and-paste
+ also works well. Sometimes, the exact output is critical to
+ finding the bug.
+
+If you can provide any of the following things, it will greatly assist
+us in fixing the problem and improve the chances that we'll get back to you:
+
+7. A diagnosis of what is causing the problem.
+
+8. A test case that can repeatably demonstrate the problem.
+
+9. A fix for the problem.
+
+ Bug reports should be sent by Internet electronic mail to
+<opie-bugs@inner.net>. This mail is run through an automated sorter that helps
+get the bug report into the hands of someone who can help you. In order to
+make that program work, we ask that you:
+
+ * Send this is normal RFC822 plain text or MIME text/plain.
+
+ * DO NOT send this or any other file as an "attachment" from
+ your mailer.
+
+ * DO NOT send a copy of your bug report to ANYONE other than
+ <opie-bugs@inner.net>. This includes listing more than one recipient
+ or sending it as a carbon-copy ("Cc:") to someone else.
+
+ * DO NOT send a copy of your bug report directly to the
+ authors or to any mailing lists. This really makes the
+ authors angry, and will be interpreted as a request to not
+ provide you with any help.
+
+ * DO NOT re-send bug reports because you didn't receive a
+ response. We attempt to respond to ALL properly submitted
+ bug reports. If we can't send mail back to you or you
+ didn't bother to follow the directions for submitting a
+ bug report, you won't receive a response.
+
+ While OPIE is NOT a supported program, we generally try to respond
+to all properly submitted bug reports as soon as we can. If your bug report
+is properly submitted so our machine sorter can process it, this usually
+takes one working day. If our machine sorter can't process your bug report,
+it usually takes a week or two.
+
+Copyright
+=========
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
diff --git a/contrib/opie/COPYRIGHT.NRL b/contrib/opie/COPYRIGHT.NRL
new file mode 100644
index 0000000..cfbffc3
--- /dev/null
+++ b/contrib/opie/COPYRIGHT.NRL
@@ -0,0 +1,68 @@
+# @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
+
+COPYRIGHT NOTICE
+
+All of the documentation and software included in this software
+distribution from the US Naval Research Laboratory (NRL) are
+copyrighted by their respective developers.
+
+Portions of the software are derived from the Net/2 and 4.4 Berkeley
+Software Distributions (BSD) of the University of California at
+Berkeley and those portions are copyright by The Regents of the
+University of California. All Rights Reserved. The UC Berkeley
+Copyright and License agreement is binding on those portions of the
+software. In all cases, the NRL developers have retained the original
+UC Berkeley copyright and license notices in the respective files in
+accordance with the UC Berkeley copyrights and license.
+
+Portions of this software and documentation were developed at NRL by
+various people. Those developers have each copyrighted the portions
+that they developed at NRL and have assigned All Rights for those
+portions to NRL. Outside the USA, NRL has copyright on some of the
+software developed at NRL. The affected files all contain specific
+copyright notices and those notices must be retained in any derived
+work.
+
+NRL LICENSE
+
+NRL grants permission for redistribution and use in source and binary
+forms, with or without modification, of the software and documentation
+created at NRL provided that the following conditions are met:
+
+1. All terms of the UC Berkeley copyright and license must be followed.
+2. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+3. 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.
+4. All advertising materials mentioning features or use of this software
+ must display the following acknowledgements:
+
+ This product includes software developed by the University of
+ California, Berkeley and its contributors.
+
+ This product includes software developed at the Information
+ Technology Division, US Naval Research Laboratory.
+
+5. Neither the name of the NRL nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL 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 NRL 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.
+
+The views and conclusions contained in the software and documentation
+are those of the authors and should not be interpreted as representing
+official policies, either expressed or implied, of the US Naval
+Research Laboratory (NRL).
+
+----------------------------------------------------------------------
diff --git a/contrib/opie/INSTALL b/contrib/opie/INSTALL
new file mode 100644
index 0000000..8551cb5
--- /dev/null
+++ b/contrib/opie/INSTALL
@@ -0,0 +1,88 @@
+OPIE Software Distribution, Release 2.3 Installation Instructions
+======================================= =========================
+
+ Did you read the README file?
+
+ If not, please go do so, then come back here. There is information in
+the README file that you will probably need to know in order to build and use
+OPIE, and you are better off doing it before you try to compile and install
+it.
+
+ OPIE uses Autoconf to automagically figure out as much as possible
+about your system. There are four steps to installing OPIE. Please read them
+all first before attempting to do them.
+
+1. Run the "configure" script.
+
+ Normally, you will need to type:
+
+ sh configure
+
+ If you would like to use an access file to allow users from some hosts
+to log into your system without using OTPs (thus opening up a big security
+hole, but a necessary evil for some sites), type:
+
+ sh configure --enable-access-file=/etc/opieaccess
+
+ If you'd like the file to go somewhere else, adjust this appropriately.
+
+2. Edit the Makefile
+
+ The Makefile contains some options that you may wish to modify. Also
+verify that Autoconf chose the correct options for your system.
+
+ The Makefile created by Autoconf should be correct for most users
+as-is.
+
+3. Edit options.h
+
+ Most user-tweakable options are specified in this file.
+
+ The defaults should be reasonable for most users.
+
+4. Build OPIE
+
+ Normally, you will need to type:
+
+ make
+
+ If you only want to build the client programs, type:
+
+ make client
+
+ If you only want to build the server programs, type:
+
+ make server
+
+5. Verify that OPIE works on your system and install
+
+ Normall, you will need to type:
+
+ make install
+
+ If you only want to install the client programs, type:
+
+ make client-install
+
+ If you only want to install the server programs, type:
+
+ make server-install
+
+ If you encounter any problems, you may be able to run "make uninstall"
+to remove the OPIE software from your system and revert back to almost the
+way things were before.
+
+Copyright
+=========
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this document are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
diff --git a/contrib/opie/License.TIN b/contrib/opie/License.TIN
new file mode 100644
index 0000000..0ec9d21
--- /dev/null
+++ b/contrib/opie/License.TIN
@@ -0,0 +1,45 @@
+The Inner Net License, Version 2
+================================
+
+ The author(s) grant permission for redistribution and use in source and
+binary forms, with or without modification, of the software and documentation
+provided that the following conditions are met:
+
+0. If you receive a version of the software that is specifically labelled
+ as not being for redistribution (check the version message and/or README),
+ you are not permitted to redistribute that version of the software in any
+ way or form.
+1. All terms of the all other applicable copyrights and licenses must be
+ followed.
+2. Redistributions of source code must retain the authors' copyright
+ notice(s), this list of conditions, and the following disclaimer.
+3. Redistributions in binary form must reproduce the authors' copyright
+ notice(s), this list of conditions, and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+4. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement with the name(s) of the
+ authors as specified in the copyright notice(s) substituted where
+ indicated:
+
+ This product includes software developed by <name(s)>, The Inner
+ Net, and other contributors.
+
+5. Neither the name(s) of the author(s) nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY ITS AUTHORS 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 AUTHORS 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.
+
+ Please distribute a copy of this license with the software and make it
+reasonably easy for others to find.
+
+ If these license terms cause you a real problem, contact the author.
diff --git a/contrib/opie/Makefile.in b/contrib/opie/Makefile.in
new file mode 100644
index 0000000..8c7b96d
--- /dev/null
+++ b/contrib/opie/Makefile.in
@@ -0,0 +1,271 @@
+##
+# Makefile.source and Makefile: Directions for building and installing OPIE.
+#
+# %%% portions-copyright-cmetz
+# Portions of this software are Copyright 1996 by Craig Metz, All Rights
+# Reserved. The Inner Net License Version 2 applies to these portions of
+# the software.
+# You should have received a copy of the license with this software. If
+# you didn't get a copy, you may request one from <license@inner.net>.
+#
+# Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+# McDonald, All Rights Reserved. All Rights under this copyright are assigned
+# to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+# License Agreement applies to this software.
+#
+# History:
+#
+# Modified by cmetz for OPIE 2.3. Removed manual config -- it's
+# Autoconf or bust. Replaced user configuration options
+# with options.h. Eliminated unused variables. Pass down
+# $(DEBUG) instead of several other variables to the
+# subdirs. Extended/standard key file support. Added
+# dependencies on subdir files. Made opietest call silent.
+# Removed opie-md4, opie-md5, and key aliases. Removed
+# test target. Make uninstall remove man page aliases.
+# Modified by cmetz for OPIE 2.22. Removed @LIBOBJS@ from MISSING for
+# Autoconf target. Re-ordered LFLAGS because some ld's won't
+# include libmissing properly if it's not at the end.
+# Modified by cmetz for OPIE 2.21. Added getusershell.o to IRIX
+# missing functions.
+# Modified by cmetz for OPIE 2.2. Added NEW_PROMPTS definition.
+# Added MISSING and new flags-passing for libmissing.
+# Quote MISSING or lose. Update TEST target for FTPD
+# variable. Removed line formatting for compile commands
+# since macro expansion confuses the issue anyway.
+# Added targets for opieserv. Added targets for opietest.
+# Removed obselete options.h target. Swapped libmissing
+# and libopie. Updated manual config options. Added more
+# explanatory text. Fixed uses of old SYSV and BSD4_3
+# symbols.
+# Modified at NRL for OPIE 2.2: Renamed LDFLAGS setting to LIBS,
+# renamed LDFLAGS in targets to LFLAGS. Added targets for
+# libopie and libmissing directories. Got rid of PROTOTYPES.
+# Added opiegen. Fixed RANLIB Autoconf target.
+# Modified at NRL for OPIE 2.11: Fixed fatal mistype of Autoconf.
+# Modified at NRL for OPIE 2.1: Changed targets to reflect source
+# file name changes. Changed explanation and flags for static
+# linking. Changed opieinfo target. Removed WHOAMI. Added
+# Autoconf targets. Changed if conditionals to use test
+# instead of [. Changed SU_DIR to SU to help autoconf.
+# Changed FTPDIR and FTPDNAME to FTPD to help autoconf.
+# Changed HP-UX to HP-UX9 and HP-UX10. Make uninstall
+# target depend on config. HPUX *is* no longer necessary, but
+# something does have to be there. Sub in Autoconf @CC@.
+# Modified at NRL for OPIE 2.04: Re-worded explanation of SU_STAR_CHECK.
+# Modified at NRL for OPIE 2.02: Added SU_STAR_CHECK flag.
+# Modified at NRL for OPIE 2.01: Test target makes opiesu and opielogin
+# setuid. install target clears that. uninstall target needs to
+# remove the opiekey symlinks. opieinfo target needs to
+# substitute for $(EXISTS). ifdefs target needs to check for
+# starting hash. $(LFLAGS) and -o should be at the end of all
+# link commands to spoon-feed drain bamaged link editors. Added
+# A/UX defaults.
+# Modified heavily at NRL for OPIE 2.0.
+# Written at Bellcore for the S/Key Version 1 software distribution
+# (Makefile).
+
+#============================================================================
+# CONFIGURATION PARAMETERS -- CHANGE THESE TO SUIT YOUR MACHINE
+
+# Shell to use for make(1)
+# It's usually a good idea to leave this as-is. On some systems, ksh or bash
+# may be necessary
+SHELL=/bin/sh
+
+# OWNER is the username who should own the OPIE binaries.
+# GROUP is the groupname associated with the OPIE binaries.
+#
+OWNER=0
+GROUP=bin
+
+# Where should the OPIE standard and extended databases be stored?
+#
+# Some sites might want to put this elsewhere. If you want to use an old
+# S/Key database, you should create a link from /etc/skeykeys to /etc/opiekeys.
+STD_KEY_FILE=/etc/opiekeys
+EXT_KEY_FILE=/etc/opiekeys.ext
+
+# Are we debugging?
+#
+# The first line will build a normal version of OPIE. You should use it.
+#
+# The second is for brave souls porting OPIE to a new system or trying to
+# debug it and should definitely NOT be used to build a production copy
+# of OPIE.
+#
+# The third is the above using nifty heap debugger called "Electric Fence".
+DEBUG=-O
+#DEBUG=-DDEBUG=1 -g
+#DEBUG=-DDEBUG=1 -g -lefence
+
+# These parameters are determined by Autoconf and are probably correct.
+# If OPIE doesn't build or work right, try tweaking these.
+CC=@CC@
+YACC=@YACC@
+FTPD=@FTPD@
+LIBS=@LIBS@
+OPTIONS=@DEFS@
+EXISTS=@EXISTS@
+MKDIR=@MKDIR@
+CHOWN=@CHOWN@
+LOCALBIN=@LOCALBIN@
+LOCALMAN=@LOCALMAN@
+SU=@SU@
+ALT_SU=@ALT_SU@
+LOGIN=@LOGIN@
+
+BACKUP=opie.old
+
+CFLAGS=$(DEBUG)
+
+LFLAGS=-Llibopie -Llibmissing -lopie $(LIBS) -lmissing -lopie
+LDEPS=libmissing/libmissing.a libopie/libopie.a
+
+all: client server
+
+ifdefs:
+ egrep '^#*if*def' *.c *.h | cut -f2 -d: | sort | uniq
+
+client: libopie/libopie.a libmissing/libmissing.a opietest-passed opiekey opiegen
+
+client-install: client
+ @echo "Installing OPIE client software..."
+ @echo "Copying OPIE key-related files"
+ @if test ! -d $(LOCALBIN); then $(MKDIR) $(LOCALBIN); chmod 755 $(LOCALBIN); fi
+ @cp opiekey $(LOCALBIN)
+ @$(CHOWN) $(OWNER) $(LOCALBIN)/opiekey
+ @chgrp $(GROUP) $(LOCALBIN)/opiekey
+ @echo "Changing file permissions"
+ @chmod 0511 $(LOCALBIN)/opiekey
+ @echo "Symlinking aliases to opiekey"
+ @-ln -s $(LOCALBIN)/opiekey $(LOCALBIN)/otp-md4
+ @-ln -s $(LOCALBIN)/opiekey $(LOCALBIN)/otp-md5
+ @echo "Installing manual pages"
+ @-for i in otp-md4 otp-md5; do ln -s opiekey.1 $(LOCALMAN)/man1/$$i.1; done
+ @if test ! -d $(LOCALMAN)/man1; then $(MKDIR) $(LOCALMAN)/man1; chmod 755 $(LOCALMAN)/man1; fi; cp opiekey.1 $(LOCALMAN)/man1/opiekey.1; $(CHOWN) $(OWNER) $(LOCALMAN)/man1/opiekey.1; chgrp $(GROUP) $(LOCALMAN)/man1/opiekey.1; chmod 644 $(LOCALMAN)/man1/opiekey.1
+
+server: libopie/libopie.a libmissing/libmissing.a opietest-passed opielogin opiesu opiepasswd opieinfo opieftpd opieserv
+
+server-install: server
+ @echo "Installing OPIE server software..."
+ @echo "Copying OPIE user programs"
+ @if test ! -d $(LOCALBIN); then $(MKDIR) $(LOCALBIN); chmod 755 $(LOCALBIN); fi
+ @cp opiepasswd opieinfo $(LOCALBIN)
+ @echo "Changing ownership"
+ @$(CHOWN) $(OWNER) $(LOCALBIN)/opiepasswd $(LOCALBIN)/opieinfo
+ @chgrp $(GROUP) $(LOCALBIN)/opiepasswd $(LOCALBIN)/opieinfo
+ @echo "Changing file permissions"
+ @chmod 0555 $(LOCALBIN)/opieinfo
+ @chmod 4511 $(LOCALBIN)/opiepasswd
+ @echo "Installing OPIE system programs..."
+ @if test ! $(EXISTS) $(LOGIN).$(BACKUP); then echo "Renaming existing $(LOGIN) to $(LOGIN).$(BACKUP)"; mv $(LOGIN) $(LOGIN).$(BACKUP); echo "Clearing permissions on old $(LOGIN)"; chmod 0 $(LOGIN).$(BACKUP); fi
+ @echo "Copying opielogin to $(LOGIN)"
+ @cp opielogin $(LOGIN)
+ @echo "Changing ownership of $(LOGIN)"
+ @$(CHOWN) $(OWNER) $(LOGIN)
+ @chgrp $(GROUP) $(LOGIN)
+ @echo "Changing file permissions of $(LOGIN)"
+ @chmod 4111 $(LOGIN)
+ @if test ! $(EXISTS) $(SU).$(BACKUP); then echo "Renaming existing su to su.$(BACKUP)"; mv $(SU) $(SU).$(BACKUP); echo "Clearing permissions on old su"; chmod 0 $(SU).$(BACKUP); fi
+ @-if test ! -z "$(ALT_SU)"; then if test ! $(EXISTS) $(ALT_SU).$(BACKUP); then echo "Renaming existing su to su.$(BACKUP)"; mv $(ALT_SU) $(ALT_SU).$(BACKUP); fi; echo "Copying opiesu to su"; cp opiesu $(ALT_SU); echo "Changing ownership"; $(CHOWN) $(OWNER) $(ALT_SU); chgrp $(GROUP) $(ALT_SU); echo "Changing file permissions"; chmod 4111 $(ALT_SU); echo "Clearning permissions on old su"; chmod 0 $(ALT_SU).$(BACKUP); fi
+ @echo "Copying opiesu to su"
+ @cp opiesu $(SU)
+ @echo "Changing ownership of su"
+ @$(CHOWN) $(OWNER) $(SU)
+ @chgrp $(GROUP) $(SU)
+ @echo "Changing file permissions of su"
+ @chmod 4111 $(SU)
+ @if test ! $(EXISTS) $(FTPD).$(BACKUP); then echo "Renaming existing ftp daemon to $(FTPD).$(BACKUP)"; mv $(FTPD) $(FTPD).$(BACKUP); echo "Clearing permissions on old ftp daemon"; chmod 0 $(FTPD).$(BACKUP); fi
+ @echo "Copying OPIE ftp daemon"
+ @cp opieftpd $(FTPD)
+ @echo "Changing ownership of ftpd"
+ @$(CHOWN) $(OWNER) $(FTPD)
+ @chgrp $(GROUP) $(FTPD)
+ @echo "Changing file permissions of ftpd"
+ @chmod 0100 $(FTPD)
+ @echo "Making sure OPIE database files exist"
+ @touch $(STD_KEY_FILE) $(EXT_KEY_FILE)
+ @echo "Changing permissions of OPIE database files"
+ @chmod 0644 $(STD_KEY_FILE)
+ @chmod 0600 $(EXT_KEY_FILE)
+ @echo "Changing ownership of OPIE database files"
+ @$(CHOWN) $(OWNER) $(STD_KEY_FILE) $(EXT_KEY_FILE)
+ @chgrp $(GROUP) $(STD_KEY_FILE) $(EXT_KEY_FILE)
+ @-if test ! -z "$(ACCESS_FILE)"; then echo "Creating OPIE access file (don't say we didn't warn you)"; FILE=`echo $(ACCESS_FILE) | sed 's:^-DACCESS_FILE="\(.*\)":\1:'`; touch $$FILE; $(CHOWN) 0 $$FILE; chgrp 0 $$FILE; chmod 0444 $$FILE; fi;
+ @echo "Installing manual pages"
+ @if test ! -d $(LOCALMAN); then $(MKDIR) $(LOCALMAN); chmod 755 $(LOCALMAN); fi
+ @for i in 1 4 5 8; do for j in *.$$i; do if test ! -d $(LOCALMAN)/man$$i; then $(MKDIR) $(LOCALMAN)/man$$i; chmod 755 $(LOCALMAN)/man$$i; fi; cp $$j $(LOCALMAN)/man$$i/$$j; $(CHOWN) $(OWNER) $(LOCALMAN)/man$$i/$$j; chgrp $(GROUP) $(LOCALMAN)/man$$i/$$j; chmod 644 $(LOCALMAN)/man$$i/$$j; done; done
+ @echo "REMEMBER to run opiepasswd on your users immediately."
+
+install: client-install server-install
+
+uninstall:
+ @echo "Un-installing OPIE..."
+ @echo "Removing symlinks"
+ @-for i in otp-md4 otp-md5; do rm $(LOCALBIN)/$$i; done
+ @echo "Removing OPIE programs"
+ @-for i in opiekey opiepasswd opieinfo; do rm $(LOCALBIN)/$$i; done
+ @echo "Removing OPIE manual pages"
+ @-for i in 1 4 5 8; do for j in *.$$i; do rm $(LOCALMAN)/man$$i/$$j; done; done
+ @-rm $(LOCALMAN)/man1/otp-md4.1 $(LOCALMAN)/man1/otp-md5.1
+ @echo "Restoring old binaries"
+ @-for i in $(SU) $(ALT_SU) $(LOGIN) $(FTPD); do FILE=`basename $$i`; if test ! $(EXISTS) $$i.$(BACKUP); then echo "No $$i.$(BACKUP)! Aborting."; exit 1; else echo "Removing $$FILE"; rm $$i || true; echo "Restoring old $$FILE"; mv $$i.$(BACKUP) $$i; fi; done
+ @echo "Resetting permissions"
+ @chmod 4111 $(SU) $(LOGIN)
+ @chmod 0100 $(FTPD)
+ @if test ! -z "$(ALT_SU)"; then chmod 4111 $(ALT_SU); fi
+ @echo "OPIE is now un-installed."
+ @echo "Please verify by hand that this process worked."
+
+opietest-passed: opietest
+ -./opietest && touch opietest-passed
+
+libopie/libopie.a: libopie/*.c *.h
+ (cd libopie ; $(MAKE) libopie.a CFL='$(CFLAGS) -DSTD_KEY_FILE=\"$(STD_KEY_FILE)\" -DEXT_KEY_FILE=\"$(EXT_KEY_FILE)\"')
+
+libmissing/libmissing.a: libmissing/*.c
+ (cd libmissing ; $(MAKE) libmissing.a CFL='$(CFLAGS)')
+
+clean:
+ -rm -f *.o opiekey opiegen opielogin opiepasswd opiesu opieftpd
+ -rm -f opieserv opieinfo opietest *core* opietest-passed
+ -rm -f Makefile.munge configure.munger y.tab.c .gdb*
+ (cd libopie ; $(MAKE) clean)
+ (cd libmissing ; $(MAKE) clean)
+
+realclean: clean
+ -rm -f *~ core* "\#*\#" Makefile make.log
+ -rm -f config.log config.status config.cache config.h
+ (cd libopie ; $(MAKE) realclean)
+ (cd libmissing ; $(MAKE) realclean)
+
+opiekey: opiekey.o $(LDEPS)
+ $(CC) $(CFLAGS) opiekey.o $(LFLAGS) -o opiekey
+
+opiegen: opiegen.o $(LDEPS)
+ $(CC) $(CFLAGS) opiegen.o $(LFLAGS) -o opiegen
+
+opieserv: opieserv.o $(LDEPS)
+ $(CC) $(CFLAGS) opieserv.o $(LFLAGS) -o opieserv
+
+opieftpd: opieftpd.o glob.o logwtmp.o popen.o y.tab.o $(LDEPS)
+ $(CC) $(CFLAGS) opieftpd.o glob.o logwtmp.o popen.o y.tab.o $(LFLAGS) -o opieftpd
+
+opielogin: opielogin.o permsfile.o $(LDEPS)
+ $(CC) $(CFLAGS) opielogin.o permsfile.o $(LFLAGS) -o opielogin
+
+opiepasswd: opiepasswd.o $(LDEPS)
+ $(CC) $(CFLAGS) opiepasswd.o $(LFLAGS) -o opiepasswd
+
+opiesu: opiesu.o $(LDEPS)
+ $(CC) $(CFLAGS) opiesu.o $(LFLAGS) -o opiesu
+
+y.tab.c: ftpcmd.y
+ $(YACC) ftpcmd.y
+
+opieinfo: opieinfo.o $(LDEPS)
+ $(CC) $(CFLAGS) opieinfo.o $(LFLAGS) -o opieinfo
+
+opietest: opietest.o $(LDEPS)
+ $(CC) $(CFLAGS) opietest.o $(LFLAGS) -o opietest
diff --git a/contrib/opie/README b/contrib/opie/README
new file mode 100644
index 0000000..63b4d8c
--- /dev/null
+++ b/contrib/opie/README
@@ -0,0 +1,391 @@
+OPIE Software Distribution, Release 2.3 Important Information
+======================================= =====================
+
+Introduction
+============
+
+ "One-time Passwords In Everything" (OPIE) is a freely distributable
+software package originally developed at and for the US Naval Research
+Laboratory (NRL). Recent versions are the result of a cooperative effort
+between of NRL, several of the original NRL authors, The Inner Net, and many
+other contributors from the Internet community.
+
+ OPIE is an implementation of the One-Time Password (OTP) System that
+is being considered for the Internet standards-track. OPIE provides a one-time
+password system. The system should be secure against the passive attacks
+now commonplace on the Internet (see RFC 1704 for more details). The system
+is vulnerable to active dictionary attacks, though these are not widespread
+at present and can be detected through proper use of system audit
+software.
+
+ OPIE is primarily written for UNIX-like operating systems, but
+we are working to make applicable portions portable to other operating systems.
+The OPIE software is derived in part from and is fully interoperable with the
+Bell Communications Research (Bellcore) S/Key Release 1 software. Because
+Bellcore claims "S/Key" as a trademark for their software, NRL was forced to
+use a different name (we picked "OPIE") for this software distribution.
+
+ OPIE includes the following additions/modifications to the
+original Bellcore S/Key(tm) Version 1 software:
+
+* Just about three command installation (unpack the software, run the
+ configure script, and run make install). While we still recommend that you
+ follow instructions and test things by hand, the more adventurous can
+ install OPIE quickly.
+
+* A modified BSD FTP daemon that does OTP.
+
+* A version of su that uses OTP by default.
+
+* MD5 support. MD5 is now the default algorithm, though MD4 is still supported
+ by changing a parameter in the Makefile. This change was made because MD5 is
+ widely believed to be cryptographically stronger than MD4 (see RFC 1321).
+
+* A more portable version of MD4 has been substituted for the original MD4.
+ This should solve the endian problems that were in S/Key.
+
+* Most of the system-dependencies have been moved to a new file "opie_cfg.h".
+
+* Configuration options have been moved to the Makefile.
+
+* Isolated system dependencies (e.g. BSDisms) with appropriate #ifdefs.
+
+* Revised the opiekey(1) program to simultaneously support MD4 and MD5, with
+ the default algorithm being tunable using the MDX symbol in the Makefile.
+
+* More operating systems are supported by recent versions of OPIE, but older
+ BSD systems that aren't close to being compliant with the POSIX standard are
+ no longer supported.
+
+* Transition mechanisms are optional to prevent potential back doors.
+
+* On systems using the /etc/opieaccess transition mechanism, users can choose
+ to require the use of OPIE to login to their accounts when it would
+ otherwise be optional.
+
+* Bug fixes
+
+* Cosmetic changes
+
+* Prompts (optionally) identify specifically what kind of entry (system
+ password, secret pass phrase, or OTP response) is allowed.
+
+* Changes to mostly conform with the draft Internet OTP standard.
+
+A Glance at What's New
+======================
+
+ 2.3 September 22, 1996
+
+ Autoconf is now the only supported configuration method.
+
+ Lots of internal functions got re-written in ways that will make some
+planned future changes easier.
+
+ OTP extended responses, such as automatic re-initialization.
+
+ Support for a supplemental key file that stores information that was
+not in the original /etc/skeykeys file. This allows OPIE to store extra data
+needed for things like the OTP re-initialization extended response without
+breaking interoperability with other S/Key derived programs. This file is
+named "/etc/opiekeys.ext" by default. Unlike the standard key file, it MUST
+NOT be world readable.
+
+ OPIE should better support some of the native "features" of drain
+bamaged OSs such as AIX, HP-UX, and Solaris.
+
+ OPIE's utmp/wtmp handling has been completely re-written. This should
+solve many of the utmp/wtmp problems people have been having.
+
+ Lots of cleanups.
+
+ Bug fixes.
+
+ 2.22 May 3, 1996.
+
+ More minor bug fixes. OPIE once again works on Solaris 2.x.
+
+ 2.21 April 27, 1996.
+
+ Minor bug fixes.
+
+ 2.2 April 11, 1996.
+
+ opiesubr.c, opiesubr2.c, and a few other functions moved into
+a subdirectory and split into files with fine granularity. Ditto with
+missing function replacements. This subdirectory structure changes a lot
+of things around and more splitting like this should be expected in the
+near future.
+
+ Added opiegenerator() library function that should make it very easy
+to create OTP clients using the OPIE library (this function is subject to
+change: there are a few problems remaining to be solved). Just about re-write
+opiegetpass() to use raw I/O and got most of the OPIE programs actually using
+that function. Autoconf build fixes. Lots of bug fixes. Lots of portability
+fixes. Function declarations should be ANSI style for ANSI compilers. Several
+fixes to bring OPIE in line with the latest OTP spec. MJR DES key crunch
+de-implemented.
+
+ Added sample programs: opiegen (client) and opieserv (server).
+
+ Probably broke non-autoconf support along the way :(. I've tried to
+bring this back in sync, but it may still be broken.
+
+ 2.11 December 27, 1995.
+
+ Minor bug fixes.
+
+ 2.10 December 26, 1995.
+
+ Optional autoconf support. opieinfo is now a normal program.
+Bugs fixed -- should work much better on SunOS, HP-UX, and AIX.
+
+System Requirements
+===================
+
+ In order to build and run properly, OPIE requires:
+
+ * A UNIX-like operating system
+ * An ANSI C compiler and run-time library
+ * POSIX.1- and X/Open XPG-compliance (including termios)
+ * The BSD sockets API
+ * Approximately five megabytes of free disk space
+
+ In practice, we believe that many systems who are close to meeting
+these requirements but aren't completely there (for example, SunOS with the
+native compiler) will also work. Systems who aren't anywhere near close
+(for example, DOS) are not likely to work without major adjustments to the
+OPIE code.
+
+If OPIE Doesn't Work
+====================
+
+ First and foremost, make sure you have the latest version of OPIE. The
+latest version is available by anonymous FTP at:
+
+ ftp://ftp.nrl.navy.mil/pub/security/opie
+ and
+ ftp://ftp.inner.net/pub/opie
+
+ If you have installed the OPIE software (either through "make test"
+in (7) above or "make install" in (14)), you can run "make uninstall" from the
+OPIE software distribution directory. This should remove the OPIE software and
+restore the original system programs, but it will not work properly (and can
+even result in the total loss of the old system programs -- beware!) if the
+installation procedure itself did not work properly.
+
+ OPIE is NOT supported software. We don't promise to support you or
+even to acknowledge your mail, but we are interested in bug reports and are
+reasonable folks. We also have an interest in seeing OPIE work on as many
+systems as we can. However, if your system doesn't meet the basic requirements
+for OPIE, this will probably require an unreasonable amount of effort.
+
+ The best bug reports include a diagnosis of the problem and a fix.
+Your bug report can still be valuable if you can at least diagnose what the
+problem is. If you just tell us "it doesn't work," then we won't be able to
+do anything to help you.
+
+ We've received a number of bug reports from people that look
+interesting, only to find when we try to follow up on them that the user
+either has an invalid return address or never bothered to respond to our
+followup. Please make sure that bug reports you send us have an electronic
+mail address that we can reply to somewhere in them (if necessary, just
+put it in the message body). If we send you a response and you are unable
+to invest the time to work with us to solve the problem, please tell us --
+few things are more irritating than when someone sends us information
+about a bug that we'd like to fix and then is never heard from again.
+
+ We try to respond to all properly submitted bug reports. Improperly
+submitted bug reports will be responded to only if we have time left after
+responding to properly submitted bug reports. We deliberately ignore bug
+"reports" sent to mailing lists or USENET news groups instead of or before
+our bug report address. At the least, the latter practice is lacking in
+courtesy.
+
+ The file BUG-REPORT contains our bug reporting form. Please use it
+and follow the submission instructions in that file. We are going to switch
+to machine-parsed bug report processing sometime in the near future to make
+it easier to coordinate bug hunting.
+
+Gotchas
+=======
+
+ While an almost universal "feature", most people remain unaware that
+an intruder can log into a system, then log in again by running the "login"
+command from a shell. Because the second login is from the local host, the
+utmp entry will not show a remote login host anymore. The OPIE replacement
+for /bin/login currently carries on this behavior for compatibility reasons.
+If you would like to prevent this from happening, you should change the
+permissions of /bin/login to 0100, thus preventing unprivileged users from
+executing it. This fix should work on non-OPIE /bin/login programs as well.
+
+ On 4.3BSDish systems, the supplied /bin/login replacement obtains
+the terminal type for the console comes from the console line in the /etc/ttys
+file. Several systems contain a default entry in this file that specifies the
+console terminal type as "unknown". This is probably not what you want.
+
+ The OPIE FTP daemon responds with two 530 error messages if you have
+not yet logged in and execute a command that will also do a PORT request. This
+is a feature, not a bug, as the FTP client is really sending the server two
+commands (for instance, a PORT and a LIST if you tell your BSD FTP client to do
+a DIR command) and the server is responding to each of them with an error. The
+stock BSD FTP daemon doesn't check the PORT commands to see if you are logged
+in, so you would only get one error message. This change should not break any
+standards-compliant FTP client, but there are a number of brain-damaged GUI
+clients that have a track record for not dealing gracefully with any server
+other than the stock BSD one.
+
+ The /etc/opieaccess transition mechanism is, by definition, a security
+hole in the OPIE software because an attacker could use it to circumvent the
+requirement for OPIE authentication. You should compile the software with
+support for this file disabled unless you absolutely cannot use the software
+without it because of your environment. If you do use this support for
+transition purposes, you should move people to OTP authentication as quickly
+as possible and rebuild and reinstall OPIE with this transition support
+disabled so that you won't have a lurking security hole.
+
+ If this wasn't already clear, do not let your sequence number fall
+below about ten. If your sequence number reaches zero, your OTP sequence
+can only be reset by the superuser. System administrators should make this
+caveat known to their users.
+
+ On Solaris 2.x systems (and possibly others) running NIS+, users
+should run keylogin(1) manually after login because opielogin(1) does not
+do that automatically like the system login(1) program.
+
+ There are reports that some versions of GNU C Compiler (GCC)
+(when installed on some systems) use their own termios(4) instead of
+the system's termios(4). This can cause problems. If you are having
+compilation problems that seem to relate to termios and you are using
+GCC, you should probably verify that it is using the system's
+termios(4) and not some internal-to-GCC termios(4). One report
+indicates that Sun's C compiler works fine with SunOS 4.1.3/4.1.4 on
+SPARC, but that some version of GCC on the same system has this
+termios(4) problem. We haven't reproduced these problems ourselves
+and hence aren't sure what is happening, but we pass this along for
+your information. (This may have something to do with the use of GNU
+libc)
+
+ If a user has a valid entry in the opiekeys database but has an
+asterisk in their traditional password entry, they will not be able to
+log in via opielogin, but opielogin will decrement their sequence number
+if a valid response is received.
+
+ On some systems, the OPIE login program does not always display
+a "login:" prompt the first time. We think that this has something to do
+with the telnet daemon on those systems. (This is common on SunOS) You should
+be able to fix this by upgrading to the latest version of telnetd.
+
+ The standard HPUX compiler is severely drain bamaged. One of the
+worst parts is that it sometimes won't grok a symbol definition with forward
+slashes in them properly and can choke badly on the definition of the key
+file's location. If this happens to you, install and use GCC. (This problem
+may or may not also come up with the optional HP ANSI C compiler -- we don't
+know for sure what compilers have this problem).
+
+ As of OPIE 2.2, the seed is converted to lower case and its length is
+checked in order to comply with the OTP specification. If any of your users
+have seeds that use capital letters or are too long, they need to run the OPIE
+2.2 opiepasswd program to re-initialize their sequence to one with a different
+seed.
+
+ opielogin is a replacement for /bin/login. It is NOT an OPIE "shell."
+You can use it as one, but don't be surprised if it doesn't behave the way
+you expect. An OPIE "shell" is on the TODO list.
+
+ Clients that use opiegen() will automatically send a re-initialization
+extended response if the sequence number falls below ten. If the server does
+not support this, the user will need to log in using opiekey and reset his
+sequence manually (using opiepasswd).
+
+Gripes
+======
+
+ Is it too much to ask that certain OS vendors just do the right thing
+and not fix what isn't broken? (Look at all the ifdefs in the OPIE code and
+the answer is clear)
+
+Credits
+=======
+
+ First and foremost credit goes to Phil Karn, Neil M. Haller, and John
+S. Walden of Bellcore for creating the S/Key Version 1 software distribution
+and for making its source code freely available to the public. Without their
+work, OPIE would not exist. Neil has also invested a good amount of his time
+in the development of a standard for One-Time Passwords so that packages like
+OPIE can interoperate.
+
+ The first NRL OPIE distribution included modifications made primarily
+by Dan McDonald of the U.S. Naval Research Laboratory (NRL) during March 1994.
+The 2nd NRL OPIE distribution, which has a number of improvements in areas
+such as portability of software and ease of installation, is primarily the
+work of Ran Atkinson and Craig Metz. Other NRL contributors include Brian
+Adamson, Steve Batsell, Preston Mullen, Bao Phan, Jim Ramsey, and Georg Thomas.
+
+ Some of version 2.2 was developed at NRL and released as a work in
+progress. Most of the release version was developed by Craig Metz (also of
+NRL), others at The Inner Net, and contributors from the Internet community.
+Versions beyond 2.2 were developed outside NRL, so don't blame them if they
+don't work (But please credit them when it does. Without the NRL effort, there
+wouldn't be an OPIE).
+
+ We would like to also thank everyone who helped us by by beta testing,
+reporting bugs, suggesting improvements, and/or sending us patches. We
+appreciate your contributions -- they have helped to make OPIE more of a
+community effort. These contributors include:
+
+ Mowgli Assor
+ Lawrie Brown
+ Axel Grewe
+ "Hobbit"
+ Darren Hosking
+ Martijn Koster
+ Osamu Kurati
+ Ayamura Kikuchi
+ Ikuo Nakagawa
+ Angelo Neri
+ D. Jason Penney
+ John Perkins
+ Jim Simmons
+ Werner Wiethege
+ Wietse Venema
+
+ OPIE development at NRL was sponsored by the Information Security
+Program Office (PD 71E), U.S. Space and Naval Warfare Systems Command, Crystal
+City, Virginia.
+
+ If you have problems with OPIE, please follow the instructions under
+"If OPIE Doesn't Work." Under NO circumstances should you send trouble
+reports directly to the authors or contributors.
+
+Trademarks
+==========
+S/Key is a trademark of Bell Communications Research (Bellcore).
+UNIX is a trademark of X/Open.
+NRL is a trademark of the U. S. Naval Research Laboratory.
+
+All other trademarks are trademarks of their respective owners.
+
+The term "OPIE" is in the public domain and hence cannot be legally
+trademarked by anyone.
+
+Copyrights
+==========
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+Portions of this software are copyright 1980-1990 Regents of the
+University of California, all rights reserved. The Berkeley Software
+License Agreement specifies the terms and conditions for redistribution.
+
+Portions of this software are copyright 1990 Bell Communications Research
+(Bellcore), all rights reserved.
diff --git a/contrib/opie/acconfig.h b/contrib/opie/acconfig.h
new file mode 100644
index 0000000..27a45c4
--- /dev/null
+++ b/contrib/opie/acconfig.h
@@ -0,0 +1,118 @@
+/* acconfig.h: Extra commentary for Autoheader
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+/* Define if the closedir function returns void instead of int. */
+#undef CLOSEDIR_VOID
+
+/* Define if you want the FTP daemon to support anonymous logins. */
+#undef DOANONYMOUS
+
+/* The default value of the PATH environment variable */
+#undef DEFAULT_PATH
+
+/* Defined if the file /etc/default/login exists
+ (and, presumably, should be looked at by login) */
+#undef HAVE_ETC_DEFAULT_LOGIN
+
+/* Defined to the name of a file that contains a list of files whose
+ permissions and ownerships should be changed on login. */
+#undef HAVE_LOGIN_PERMFILE
+
+/* Defined to the name of a file that contains a list of environment
+ values that should be set on login. */
+#undef HAVE_LOGIN_ENVFILE
+
+/* Defined if the file /etc/securetty exists
+ (and, presumably, should be looked at by login) */
+#undef HAVE_SECURETTY
+
+/* Defined if the file /etc/shadow exists
+ (and, presumably, should be looked at for shadow passwords) */
+#undef HAVE_ETC_SHADOW
+
+/* The path to the access file, if we're going to use it */
+#undef PATH_ACCESS_FILE
+
+/* The path to the mail spool, if we know it */
+#undef PATH_MAIL
+
+/* The path to the utmp file, if we know it */
+#undef PATH_UTMP_AC
+
+/* The path to the utmpx file, if we know it */
+#undef PATH_UTMPX_AC
+
+/* The path to the wtmp file, if we know it */
+#undef PATH_WTMP_AC
+
+/* The path to the wtmpx file, if we know it */
+#undef PATH_WTMPX_AC
+
+/* Defined if the system's profile (/etc/profile) displays
+ the motd file */
+#undef HAVE_MOTD_IN_PROFILE
+
+/* Defined if the system's profile (/etc/profile) informs the
+ user of new mail */
+#undef HAVE_MAILCHECK_IN_PROFILE
+
+/* Define if you have a nonstandard gettimeofday() that takes one argument
+ instead of two. */
+#undef HAVE_ONE_ARG_GETTIMEOFDAY
+
+/* Define if the system has the getenv function */
+#undef HAVE_GETENV
+
+/* Define if the system has the setenv function */
+#undef HAVE_SETENV
+
+/* Define if the system has the /var/adm/sulog file */
+#undef HAVE_SULOG
+
+/* Define if the system has the unsetenv function */
+#undef HAVE_UNSETENV
+
+/* Define if the compiler can handle ANSI-style argument lists */
+#undef HAVE_ANSIDECL
+
+/* Define if the compiler can handle ANSI-style prototypes */
+#undef HAVE_ANSIPROTO
+
+/* Define if the system has an ANSI-style printf (returns int instead of char *) */
+#undef HAVE_ANSISPRINTF
+
+/* Define if the compiler can handle ANSI-style variable argument lists */
+#undef HAVE_ANSISTDARG
+
+/* Define if the compiler can handle void argument lists to functions */
+#undef HAVE_VOIDARG
+
+/* Define if the compiler can handle void return "values" from functions */
+#undef HAVE_VOIDRET
+
+/* Define if the compiler can handle void pointers to our liking */
+#undef HAVE_VOIDPTR
+
+/* Define if the /bin/ls command seems to support the -g flag */
+#undef HAVE_LS_G_FLAG
+
+/* Define if there is a ut_pid field in struct utmp */
+#undef HAVE_UT_PID
+
+/* Define if there is a ut_type field in struct utmp */
+#undef HAVE_UT_TYPE
+
+/* Define if there is a ut_user field in struct utmp */
+#undef HAVE_UT_USER
+
+/* Define if there is a ut_name field in struct utmp */
+#undef HAVE_UT_NAME
+
+/* Define if there is a ut_host field in struct utmp */
+#undef HAVE_UT_HOST
diff --git a/contrib/opie/config.h.in b/contrib/opie/config.h.in
new file mode 100644
index 0000000..1fdbff9
--- /dev/null
+++ b/contrib/opie/config.h.in
@@ -0,0 +1,324 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if on MINIX. */
+#undef _MINIX
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you want the FTP daemon to support anonymous logins. */
+#undef DOANONYMOUS
+
+/* The default value of the PATH environment variable */
+#undef DEFAULT_PATH
+
+/* Defined if the file /etc/default/login exists
+ (and, presumably, should be looked at by login) */
+#undef HAVE_ETC_DEFAULT_LOGIN
+
+/* Defined to the name of a file that contains a list of files whose
+ permissions and ownerships should be changed on login. */
+#undef HAVE_LOGIN_PERMFILE
+
+/* Defined to the name of a file that contains a list of environment
+ values that should be set on login. */
+#undef HAVE_LOGIN_ENVFILE
+
+/* Defined if the file /etc/securetty exists
+ (and, presumably, should be looked at by login) */
+#undef HAVE_SECURETTY
+
+/* Defined if the file /etc/shadow exists
+ (and, presumably, should be looked at for shadow passwords) */
+#undef HAVE_ETC_SHADOW
+
+/* The path to the access file, if we're going to use it */
+#undef PATH_ACCESS_FILE
+
+/* The path to the mail spool, if we know it */
+#undef PATH_MAIL
+
+/* Defined if the system's profile (/etc/profile) displays
+ the motd file */
+#undef HAVE_MOTD_IN_PROFILE
+
+/* Defined if the system's profile (/etc/profile) informs the
+ user of new mail */
+#undef HAVE_MAILCHECK_IN_PROFILE
+
+/* Define if you have a nonstandard gettimeofday() that takes one argument
+ instead of two. */
+#undef HAVE_ONE_ARG_GETTIMEOFDAY
+
+/* Define if the system has the getenv function */
+#undef HAVE_GETENV
+
+/* Define if the system has the setenv function */
+#undef HAVE_SETENV
+
+/* Define if the system has the /var/adm/sulog file */
+#undef HAVE_SULOG
+
+/* Define if the system has the unsetenv function */
+#undef HAVE_UNSETENV
+
+/* Define if the compiler can handle ANSI-style argument lists */
+#undef HAVE_ANSIDECL
+
+/* Define if the compiler can handle ANSI-style prototypes */
+#undef HAVE_ANSIPROTO
+
+/* Define if the system has an ANSI-style printf (returns int instead of char *) */
+#undef HAVE_ANSISPRINTF
+
+/* Define if the compiler can handle ANSI-style variable argument lists */
+#undef HAVE_ANSISTDARG
+
+/* Define if the compiler can handle void argument lists to functions */
+#undef HAVE_VOIDARG
+
+/* Define if the compiler can handle void return "values" from functions */
+#undef HAVE_VOIDRET
+
+/* Define if the compiler can handle void pointers to our liking */
+#undef HAVE_VOIDPTR
+
+/* Define if the /bin/ls command seems to support the -g flag */
+#undef HAVE_LS_G_FLAG
+
+/* Define if there is a ut_pid field in struct utmp */
+#undef HAVE_UT_PID
+
+/* Define if there is a ut_type field in struct utmp */
+#undef HAVE_UT_TYPE
+
+/* Define if there is a ut_name field in struct utmp */
+#undef HAVE_UT_NAME
+
+/* Define if there is a ut_host field in struct utmp */
+#undef HAVE_UT_HOST
+
+/* Define if you have the bcopy function. */
+#undef HAVE_BCOPY
+
+/* Define if you have the bzero function. */
+#undef HAVE_BZERO
+
+/* Define if you have the endspent function. */
+#undef HAVE_ENDSPENT
+
+/* Define if you have the fpurge function. */
+#undef HAVE_FPURGE
+
+/* Define if you have the getdtablesize function. */
+#undef HAVE_GETDTABLESIZE
+
+/* Define if you have the getgroups function. */
+#undef HAVE_GETGROUPS
+
+/* Define if you have the gethostname function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the getspent function. */
+#undef HAVE_GETSPENT
+
+/* Define if you have the gettimeofday function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the getttynam function. */
+#undef HAVE_GETTTYNAM
+
+/* Define if you have the getutxline function. */
+#undef HAVE_GETUTXLINE
+
+/* Define if you have the getwd function. */
+#undef HAVE_GETWD
+
+/* Define if you have the index function. */
+#undef HAVE_INDEX
+
+/* Define if you have the lstat function. */
+#undef HAVE_LSTAT
+
+/* Define if you have the pututxline function. */
+#undef HAVE_PUTUTXLINE
+
+/* Define if you have the rindex function. */
+#undef HAVE_RINDEX
+
+/* Define if you have the setegid function. */
+#undef HAVE_SETEGID
+
+/* Define if you have the seteuid function. */
+#undef HAVE_SETEUID
+
+/* Define if you have the setgroups function. */
+#undef HAVE_SETGROUPS
+
+/* Define if you have the setlogin function. */
+#undef HAVE_SETLOGIN
+
+/* Define if you have the setpriority function. */
+#undef HAVE_SETPRIORITY
+
+/* Define if you have the setregid function. */
+#undef HAVE_SETREGID
+
+/* Define if you have the setresgid function. */
+#undef HAVE_SETRESGID
+
+/* Define if you have the setresuid function. */
+#undef HAVE_SETRESUID
+
+/* Define if you have the setreuid function. */
+#undef HAVE_SETREUID
+
+/* Define if you have the setvbuf function. */
+#undef HAVE_SETVBUF
+
+/* Define if you have the sigblock function. */
+#undef HAVE_SIGBLOCK
+
+/* Define if you have the sigsetmask function. */
+#undef HAVE_SIGSETMASK
+
+/* Define if you have the socket function. */
+#undef HAVE_SOCKET
+
+/* Define if you have the strftime function. */
+#undef HAVE_STRFTIME
+
+/* Define if you have the strstr function. */
+#undef HAVE_STRSTR
+
+/* Define if you have the sysconf function. */
+#undef HAVE_SYSCONF
+
+/* Define if you have the ttyslot function. */
+#undef HAVE_TTYSLOT
+
+/* Define if you have the <crypt.h> header file. */
+#undef HAVE_CRYPT_H
+
+/* Define if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <lastlog.h> header file. */
+#undef HAVE_LASTLOG_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <ndir.h> header file. */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define if you have the <shadow.h> header file. */
+#undef HAVE_SHADOW_H
+
+/* Define if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <sys/dir.h> header file. */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define if you have the <sys/ndir.h> header file. */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/signal.h> header file. */
+#undef HAVE_SYS_SIGNAL_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/utsname.h> header file. */
+#undef HAVE_SYS_UTSNAME_H
+
+/* Define if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
+
+/* Define if you have the crypt library (-lcrypt). */
+#undef HAVE_LIBCRYPT
+
+/* Define if you have the nsl library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define if you have the posix library (-lposix). */
+#undef HAVE_LIBPOSIX
+
+/* Define if you have the socket library (-lsocket). */
+#undef HAVE_LIBSOCKET
diff --git a/contrib/opie/config.testeflag b/contrib/opie/config.testeflag
new file mode 100644
index 0000000..cc16df4
--- /dev/null
+++ b/contrib/opie/config.testeflag
@@ -0,0 +1,12 @@
+#! /bin/sh
+if test -e README >/dev/null 2>/dev/null
+then
+ if test -e a.non-existant-file >/dev/null 2>/dev/null
+ then
+ exit 1
+ else
+ exit 0
+ fi
+else
+ exit 1
+fi
diff --git a/contrib/opie/configure b/contrib/opie/configure
new file mode 100755
index 0000000..f635e08
--- /dev/null
+++ b/contrib/opie/configure
@@ -0,0 +1,4089 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.10
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-access-file=PATH Use the OPIE access file PATH as a transition aid"
+ac_help="$ac_help
+ --enable-anonymous-ftp Enable anonymous FTP support"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.10"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=README
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# Check whether --enable-access-file or --disable-access-file was given.
+if test "${enable_access_file+set}" = set; then
+ enableval="$enable_access_file"
+ cat >> confdefs.h <<EOF
+#define PATH_ACCESS_FILE "$enable_access_file"
+EOF
+ echo "Using the access file in $enable_access_file -- don't say we didn't warn you!"
+fi
+
+# Check whether --enable-anonymous-ftp or --disable-anonymous-ftp was given.
+if test "${enable_anonymous_ftp+set}" = set; then
+ enableval="$enable_anonymous_ftp"
+ cat >> confdefs.h <<\EOF
+#define DOANONYMOUS 1
+EOF
+ echo "Enabling anonymous FTP support in ftp -- don't say we didn't warn you!"
+fi
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:626: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ if test "${CFLAGS+set}" != set; then
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_gcc_g=yes
+else
+ ac_cv_prog_gcc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
+ if test $ac_cv_prog_gcc_g = yes; then
+ CFLAGS="-g -O"
+ else
+ CFLAGS="-O"
+ fi
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 678 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 693 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:699: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_YACC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+ echo "$ac_t""$YACC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+
+echo $ac_n "checking for AIX""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 803 "configure"
+#include "confdefs.h"
+#ifdef _AIX
+ yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define _ALL_SOURCE 1
+EOF
+
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+
+ac_safe=`echo "minix/config.h" | tr './\055' '___'`
+echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 850 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:855: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ MINIX=yes
+else
+ echo "$ac_t""no" 1>&6
+MINIX=
+fi
+
+if test "$MINIX" = yes; then
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_1_SOURCE 2
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _MINIX 1
+EOF
+
+fi
+
+
+# If we cannot run a trivial program, we must be cross compiling.
+echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_cross=yes
+else
+cat > conftest.$ac_ext <<EOF
+#line 900 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+{ (eval echo configure:904: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_cross=no
+else
+ ac_cv_c_cross=yes
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_cross" 1>&6
+cross_compiling=$ac_cv_c_cross
+
+
+
+# Extract the first word of "chown", so it can be a program name with args.
+set dummy chown; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_CHOWN'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$CHOWN" in
+ /*)
+ ac_cv_path_CHOWN="$CHOWN" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/bin /bin /usr/sbin /sbin /usr/etc /etc; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_CHOWN="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_CHOWN" && ac_cv_path_CHOWN="/bin/chown"
+ ;;
+esac
+fi
+CHOWN="$ac_cv_path_CHOWN"
+if test -n "$CHOWN"; then
+ echo "$ac_t""$CHOWN" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+# Extract the first word of "su", so it can be a program name with args.
+set dummy su; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_SU'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$SU" in
+ /*)
+ ac_cv_path_SU="$SU" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/bin /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_SU="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_SU" && ac_cv_path_SU="/bin/su"
+ ;;
+esac
+fi
+SU="$ac_cv_path_SU"
+if test -n "$SU"; then
+ echo "$ac_t""$SU" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "su", so it can be a program name with args.
+set dummy su; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_ALT_SU'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$ALT_SU" in
+ /*)
+ ac_cv_path_ALT_SU="$ALT_SU" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/sbin /sbin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_ALT_SU="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+ALT_SU="$ac_cv_path_ALT_SU"
+if test -n "$ALT_SU"; then
+ echo "$ac_t""$ALT_SU" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+# Extract the first word of "scheme", so it can be a program name with args.
+set dummy scheme; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_SCHEME'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$SCHEME" in
+ /*)
+ ac_cv_path_SCHEME="$SCHEME" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/lib/iaf/scheme; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_SCHEME="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+SCHEME="$ac_cv_path_SCHEME"
+if test -n "$SCHEME"; then
+ echo "$ac_t""$SCHEME" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "login", so it can be a program name with args.
+set dummy login; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_LOGIN'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$LOGIN" in
+ /*)
+ ac_cv_path_LOGIN="$LOGIN" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/bin /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_LOGIN="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_LOGIN" && ac_cv_path_LOGIN="/bin/login"
+ ;;
+esac
+fi
+LOGIN="$ac_cv_path_LOGIN"
+if test -n "$LOGIN"; then
+ echo "$ac_t""$LOGIN" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test ! -z "$SCHEME";
+then
+ LOGIN="$SCHEME";
+fi
+
+# Extract the first word of "ftpd", so it can be a program name with args.
+set dummy ftpd; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_FTPD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$FTPD" in
+ /*)
+ ac_cv_path_FTPD="$FTPD" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_FTPD="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+FTPD="$ac_cv_path_FTPD"
+if test -n "$FTPD"; then
+ echo "$ac_t""$FTPD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "in.ftpd", so it can be a program name with args.
+set dummy in.ftpd; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_INFTPD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$INFTPD" in
+ /*)
+ ac_cv_path_INFTPD="$INFTPD" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_INFTPD="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+INFTPD="$ac_cv_path_INFTPD"
+if test -n "$INFTPD"; then
+ echo "$ac_t""$INFTPD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$FTPD"
+then
+ if test ! -z "$INFTPD"
+ then
+ FTPD="$INFTPD"
+ fi
+fi
+
+echo $ac_n "checking for default PATH entries""... $ac_c" 1>&6
+default_path=""
+save_IFS="$IFS"
+IFS=" "
+for i in /usr/bin /bin /usr/ucb /usr/sbin /usr/bsd /sbin /usr/bin/X11 /etc /usr/local/X11/bin /usr/X11R6/bin /your-system-is-broken
+do
+ IFS=":"
+ for j in $PATH
+ do
+ if test "$i" = "$j"
+ then
+ if test -d "$i"
+ then
+ if test -z "$default_path"
+ then
+ default_path="$i"
+ else
+ default_path="$default_path:$i"
+ fi
+ fi
+ fi
+ done
+ IFS=" "
+done
+cat >> confdefs.h <<EOF
+#define DEFAULT_PATH "$default_path"
+EOF
+
+echo "$ac_t""$default_path" 1>&6
+
+echo $ac_n "checking for test -e flag""... $ac_c" 1>&6
+if sh config.testeflag
+then
+ result=yes
+ EXISTS="-e"
+else
+ result=no
+ EXISTS="-f"
+fi
+
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking for mkdir -p flag""... $ac_c" 1>&6
+if test -d config.tmpdir
+then
+ rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null
+ rmdir config.tmpdir/foo >/dev/null 2>/dev/null
+ rmdir config.tmpdir >/dev/null 2>/dev/null
+fi
+
+result=no
+if mkdir -p config.tmpdir/foo/bar >/dev/null 2>/dev/null
+then
+ if test -d config.tmpdir
+ then
+ if test -d config.tmpdir/foo
+ then
+ if test -d config.tmpdir/foo/bar
+ then
+ result=yes
+ rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null
+ fi
+ rmdir config.tmpdir/foo >/dev/null 2>/dev/null
+ fi
+ rmdir config.tmpdir >/dev/null 2>/dev/null
+ fi
+fi
+
+if test "$result" = yes
+then
+ MKDIR="mkdir -p"
+else
+ MKDIR="mkdir"
+fi
+
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking for ls group field""... $ac_c" 1>&6
+lsg=`/bin/ls -ldg / | wc -w | awk '{print $1}'`;
+ls=`/bin/ls -ld / | wc -w | awk '{print $1}'`;
+result="no"
+if test $ls = 9;
+then
+ result="yes"
+else
+ if test "$ls" = 8 -a "$lsg" = 9;
+ then
+ result="yes, with -g"
+ cat >> confdefs.h <<\EOF
+#define HAVE_LS_G_FLAG 1
+EOF
+
+ fi
+fi
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking for /etc/default/login""... $ac_c" 1>&6
+if test $EXISTS /etc/default/login
+then
+ result=yes
+ cat >> confdefs.h <<\EOF
+#define HAVE_ETC_DEFAULT_LOGIN 1
+EOF
+
+else
+ result=no
+fi
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking for /etc/securetty""... $ac_c" 1>&6
+if test $EXISTS /etc/securetty
+then
+ result=yes
+ cat >> confdefs.h <<\EOF
+#define HAVE_SECURETTY 1
+EOF
+
+else
+ result=no
+fi
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking for /etc/logindevperm""... $ac_c" 1>&6
+if test $EXISTS /etc/logindevperm
+then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_LOGIN_PERMFILE "/etc/logindevperm"
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+
+ echo $ac_n "checking for /etc/fbtab""... $ac_c" 1>&6
+ if test $EXISTS /etc/fbtab
+ then
+ result=yes
+ cat >> confdefs.h <<\EOF
+#define HAVE_LOGIN_PERMFILE "/etc/fbtab"
+EOF
+
+ else
+ result=no
+ fi
+ echo "$ac_t""$result" 1>&6
+fi
+
+echo $ac_n "checking for /etc/environment""... $ac_c" 1>&6
+if test $EXISTS /etc/environment
+then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_LOGIN_ENVFILE "/etc/environment"
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+
+ echo $ac_n "checking for /etc/src.sh""... $ac_c" 1>&6
+ if test $EXISTS /etc/src.sh
+ then
+ result=yes
+ cat >> confdefs.h <<\EOF
+#define HAVE_LOGIN_ENVFILE "/etc/src.sh"
+EOF
+
+ else
+ result=no
+ fi
+ echo "$ac_t""$result" 1>&6
+fi
+
+echo $ac_n "checking for /etc/shadow""... $ac_c" 1>&6
+if test $EXISTS /etc/shadow
+then
+ result=yes
+ cat >> confdefs.h <<\EOF
+#define HAVE_ETC_SHADOW 1
+EOF
+
+else
+ result=no
+fi
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking for /var/adm/sulog""... $ac_c" 1>&6
+if test $EXISTS /var/adm/sulog
+then
+ result=yes
+ cat >> confdefs.h <<\EOF
+#define HAVE_SULOG 1
+EOF
+
+else
+ result=no
+fi
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking mail spool location""... $ac_c" 1>&6
+mail_spool=""
+for i in /var/mail /usr/mail /var/spool/mail /usr/spool/mail
+do
+ if test -d $i
+ then
+ mail_spool="$i"
+ fi
+done
+if test -z "$mail_spool"
+then
+ result="not found"
+else
+ result="$mail_spool"
+ cat >> confdefs.h <<EOF
+#define PATH_MAIL "$mail_spool"
+EOF
+
+fi
+echo "$ac_t""$result" 1>&6
+
+
+
+echo $ac_n "checking whether the system profile displays the motd""... $ac_c" 1>&6
+result=no
+if test $EXISTS /etc/profile
+then
+ if grep motd /etc/profile >/dev/null 2>/dev/null
+ then
+ result=yes
+ fi
+fi
+if test "$result" = yes
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MOTD_IN_PROFILE 1
+EOF
+
+fi
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking whether the system profile checks for mail""... $ac_c" 1>&6
+result=no
+if test $EXISTS /etc/profile
+then
+ if grep 'mail\.' /etc/profile >/dev/null 2>/dev/null
+ then
+ result=yes
+ fi
+fi
+if test "$result" = yes
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MAILCHECK_IN_PROFILE 1
+EOF
+
+fi
+echo "$ac_t""$result" 1>&6
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1411 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1461: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+
+echo $ac_n "checking to see if your compiler can handle void arguments""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 1483 "configure"
+#include "confdefs.h"
+foo(void) { }
+int main() { return 0; }
+int t() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1491: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_VOIDARG 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking to see if your compiler can handle void return values""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 1506 "configure"
+#include "confdefs.h"
+void foo() { }
+int main() { return 0; }
+int t() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1514: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_VOIDRET 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking to see if your compiler can handle void pointers""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 1529 "configure"
+#include "confdefs.h"
+foo() { void *bar = (void *)0x42; bar = bar + 1; }
+int main() { return 0; }
+int t() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1537: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_VOIDPTR 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking to see if your compiler can handle ANSI argument lists""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 1552 "configure"
+#include "confdefs.h"
+int foo(int bar, int baz) { return 0; }
+int main() { return 0; }
+int t() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1560: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_ANSIDECL 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking to see if your compiler can handle ANSI prototypes""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 1575 "configure"
+#include "confdefs.h"
+extern int foo(int, int);
+int main() { return 0; }
+int t() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1583: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_ANSIPROTO 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking to see if your compiler can handle ANSI variable arguments""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 1598 "configure"
+#include "confdefs.h"
+#include <stdarg.h>
+int foo(int arg, ...) {
+ va_list ap;
+ va_start(ap, arg);
+ va_end(ap);
+ return 0;
+}
+int main() { return 0; }
+int t() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1612: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_ANSISTDARG 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking to see if you have an ANSI-style sprintf""... $ac_c" 1>&6
+if test "$cross_compiling" = yes; then
+ echo "$ac_t""no" 1>&6
+else
+cat > conftest.$ac_ext <<EOF
+#line 1630 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ char buf[5];
+ int i = 2;
+ i += sprintf(buf, "1234");
+ return (i == 6) ? 0 : -1;
+}
+EOF
+{ (eval echo configure:1643: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ANSISPRINTF 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+fi
+rm -fr conftest*
+
+echo $ac_n "checking for -lcrypt""... $ac_c" 1>&6
+ac_lib_var=`echo crypt'_'crypt | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcrypt $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1663 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char crypt();
+
+int main() { return 0; }
+int t() {
+crypt()
+; return 0; }
+EOF
+if { (eval echo configure:1675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo crypt | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lcrypt $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for -lnsl""... $ac_c" 1>&6
+ac_lib_var=`echo nsl'_'gethostname | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1707 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostname();
+
+int main() { return 0; }
+int t() {
+gethostname()
+; return 0; }
+EOF
+if { (eval echo configure:1719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo nsl | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lnsl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for -lposix""... $ac_c" 1>&6
+ac_lib_var=`echo posix'_'main | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lposix $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1751 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo posix | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lposix $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for -lsocket""... $ac_c" 1>&6
+ac_lib_var=`echo socket'_'socket | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1791 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() { return 0; }
+int t() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1803: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo socket | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsocket $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1837 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() { return 0; }
+int t() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:1846: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdedfghijklmnopqrstuvwxyz./\055' 'ABCDEDFGHIJKLMNOPQRSTUVWXYZ___'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for -ldir""... $ac_c" 1>&6
+ac_lib_var=`echo dir'_'opendir | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldir $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1877 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() { return 0; }
+int t() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1889: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ldir"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for -lx""... $ac_c" 1>&6
+ac_lib_var=`echo x'_'opendir | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lx $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1916 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() { return 0; }
+int t() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1928: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lx"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1953 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() { return 0; }
+int t() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:1970: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in crypt.h fcntl.h limits.h termios.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h paths.h shadow.h signal.h sys/signal.h lastlog.h sys/utsname.h pwd.h sys/param.h string.h stdlib.h utmpx.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1997 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+echo $ac_n "checking for ut_pid in struct utmp""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 2030 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <utmp.h>
+int main() { return 0; }
+int t() {
+struct utmp foo; return (int)foo.ut_pid;
+; return 0; }
+EOF
+if { (eval echo configure:2039: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_UT_PID 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking for ut_type in struct utmp""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 2053 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <utmp.h>
+int main() { return 0; }
+int t() {
+struct utmp foo; return (int)foo.ut_type;
+; return 0; }
+EOF
+if { (eval echo configure:2062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_UT_TYPE 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking for ut_name in struct utmp""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 2076 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <utmp.h>
+int main() { return 0; }
+int t() {
+struct utmp foo; return (int)foo.ut_name[0];
+; return 0; }
+EOF
+if { (eval echo configure:2085: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_UT_NAME 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+cat >> confdefs.h <<\EOF
+#define HAVE_UT_HOST 1
+EOF
+
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2107 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() { return 0; }
+int t() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:2125: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+for ac_func in gettimeofday socket strftime strstr setpriority seteuid setreuid setegid setregid setresuid setresgid getttynam sysconf setvbuf getspent endspent setgroups getgroups fpurge setlogin lstat getutxline pututxline
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2149 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2173: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_memcmp'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_memcmp=no
+else
+cat > conftest.$ac_ext <<EOF
+#line 2204 "configure"
+#include "confdefs.h"
+
+main()
+{
+ char c0 = 0x40, c1 = 0x80, c2 = 0x81;
+ exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
+}
+
+EOF
+{ (eval echo configure:2214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_func_memcmp=yes
+else
+ ac_cv_func_memcmp=no
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_memcmp" 1>&6
+test $ac_cv_func_memcmp = no && LIBOBJS="$LIBOBJS memcmp.o"
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2234 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() { return 0; }
+int t() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:2242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_alloca'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2266 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+#endif
+
+int main() { return 0; }
+int t() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:2290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_func_alloca=yes
+else
+ rm -rf conftest*
+ ac_cv_func_alloca=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_func_alloca" 1>&6
+if test $ac_cv_func_alloca = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.o
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2325 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2354 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2378: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+cat > conftest.$ac_ext <<EOF
+#line 2410 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+{ (eval echo configure:2429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_stack_direction=1
+else
+ ac_cv_c_stack_direction=-1
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_func in getusershell sigaddset sigemptyset strerror strncasecmp
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2453 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2477: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.o"
+fi
+
+done
+
+MISSING="$LIBOBJS $ALLOCA "
+echo $ac_n "checking for atexit""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_atexit'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2503 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char atexit(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char atexit();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_atexit) || defined (__stub___atexit)
+choke me
+#else
+atexit();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_atexit=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_atexit=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'atexit`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}atexit.o "
+fi
+
+echo $ac_n "checking for entutent""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_entutent'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2550 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char entutent(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char entutent();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_entutent) || defined (__stub___entutent)
+choke me
+#else
+entutent();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_entutent=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_entutent=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'entutent`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}endutent.o "
+fi
+
+echo $ac_n "checking for memcpy""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_memcpy'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2597 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char memcpy(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char memcpy();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_memcpy) || defined (__stub___memcpy)
+choke me
+#else
+memcpy();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2621: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_memcpy=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_memcpy=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'memcpy`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}memcpy.o "; for ac_func in bcopy
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2643 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for memset""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_memset'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2696 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char memset(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char memset();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_memset) || defined (__stub___memset)
+choke me
+#else
+memset();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2720: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_memset=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_memset=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'memset`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}memset.o "; for ac_func in bzero
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2742 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for getcwd""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_getcwd'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2795 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getcwd(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getcwd();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_getcwd) || defined (__stub___getcwd)
+choke me
+#else
+getcwd();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2819: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_getcwd=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_getcwd=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'getcwd`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}getcwd.o "; for ac_func in getwd
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2841 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for getenv""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_getenv'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2894 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getenv(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getenv();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_getenv) || defined (__stub___getenv)
+choke me
+#else
+getenv();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2918: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_getenv=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_getenv=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'getenv`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_GETENV 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}env.o "
+fi
+
+echo $ac_n "checking for getutline""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_getutline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2944 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getutline(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getutline();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_getutline) || defined (__stub___getutline)
+choke me
+#else
+getutline();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2968: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_getutline=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_getutline=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'getutline`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}getutline.o "; for ac_func in ttyslot
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2990 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3014: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for pututline""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_pututline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3043 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pututline(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char pututline();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_pututline) || defined (__stub___pututline)
+choke me
+#else
+pututline();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3067: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_pututline=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_pututline=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'pututline`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}pututline.o "; for ac_func in ttyslot
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3089 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for setenv""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_setenv'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3142 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char setenv(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char setenv();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_setenv) || defined (__stub___setenv)
+choke me
+#else
+setenv();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3166: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_setenv=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_setenv=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'setenv`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_SETENV 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}env.o "
+fi
+
+echo $ac_n "checking for sigprocmask""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_sigprocmask'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3192 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sigprocmask(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sigprocmask();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_sigprocmask) || defined (__stub___sigprocmask)
+choke me
+#else
+sigprocmask();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3216: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_sigprocmask=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_sigprocmask=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'sigprocmask`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}sigprocmask.o "; for ac_func in sigblock sigsetmask
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3238 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3262: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for strchr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_strchr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3291 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strchr(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strchr();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_strchr) || defined (__stub___strchr)
+choke me
+#else
+strchr();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_strchr=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_strchr=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'strchr`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}strchr.o "; for ac_func in index
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3337 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3361: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for strrchr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_strrchr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3390 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strrchr(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strrchr();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_strrchr) || defined (__stub___strrchr)
+choke me
+#else
+strrchr();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3414: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_strrchr=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_strrchr=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'strrchr`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}strrchr.o "; for ac_func in rindex
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3436 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3460: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for sysconf""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_sysconf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3489 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sysconf(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sysconf();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_sysconf) || defined (__stub___sysconf)
+choke me
+#else
+sysconf();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_sysconf=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_sysconf=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'sysconf`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}sysconf.o "; for ac_func in getdtablesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3535 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for uname""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_uname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3588 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char uname(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char uname();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_uname) || defined (__stub___uname)
+choke me
+#else
+uname();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_uname=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_uname=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'uname`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}uname.o "; for ac_func in gethostname
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3634 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for unsetenv""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_unsetenv'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3687 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char unsetenv(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char unsetenv();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_unsetenv) || defined (__stub___unsetenv)
+choke me
+#else
+unsetenv();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_unsetenv=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_unsetenv=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'unsetenv`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_UNSETENV 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+MISSING="${MISSING}env.o "
+fi
+
+
+
+echo $ac_n "checking for nonstandard gettimeofday""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 3736 "configure"
+#include "confdefs.h"
+
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+int main() { return 0; }
+int t() {
+struct timeval tv;
+gettimeofday(&tv, NULL)
+; return 0; }
+EOF
+if { (eval echo configure:3752: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""maybe" 1>&6 cat > conftest.$ac_ext <<EOF
+#line 3758 "configure"
+#include "confdefs.h"
+
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+int main() { return 0; }
+int t() {
+struct timeval tv;
+gettimeofday(&tv)
+; return 0; }
+EOF
+if { (eval echo configure:3774: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_ONE_ARG_GETTIMEOFDAY 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+
+# Munge out LOCALBIN and LOCALMAN in canonical (no bletch) form
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+ >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.10"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "configure.munger libmissing/Makefile libopie/Makefile Makefile.munge:Makefile.in config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@LN_S@%$LN_S%g
+s%@RANLIB@%$RANLIB%g
+s%@YACC@%$YACC%g
+s%@CHOWN@%$CHOWN%g
+s%@SU@%$SU%g
+s%@ALT_SU@%$ALT_SU%g
+s%@SCHEME@%$SCHEME%g
+s%@LOGIN@%$LOGIN%g
+s%@FTPD@%$FTPD%g
+s%@INFTPD@%$INFTPD%g
+s%@EXISTS@%$EXISTS%g
+s%@MKDIR@%$MKDIR%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@ALLOCA@%$ALLOCA%g
+s%@MISSING@%$MISSING%g
+
+CEOF
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"configure.munger libmissing/Makefile libopie/Makefile Makefile.munge:Makefile.in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust relative srcdir, etc. for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+fi; done
+rm -f conftest.subs
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"}
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ cp $ac_given_srcdir/$ac_file_in conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+# Maximum number of lines to put in a single here document.
+ac_max_here_lines=12
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+sh configure.munger
diff --git a/contrib/opie/configure.in b/contrib/opie/configure.in
new file mode 100644
index 0000000..91c1a35
--- /dev/null
+++ b/contrib/opie/configure.in
@@ -0,0 +1,455 @@
+dnl configure.in: Input for Autoconf
+dnl
+dnl %%% portions-copyright-cmetz
+dnl Portions of this software are Copyright 1996 by Craig Metz, All Rights
+dnl Reserved. The Inner Net License Version 2 applies to these portions of
+dnl the software.
+dnl You should have received a copy of the license with this software. If
+dnl you didn't get a copy, you may request one from <license@inner.net>.
+dnl
+dnl Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+dnl McDonald, All Rights Reserved. All Rights under this copyright are assigned
+dnl to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+dnl License Agreement applies to this software.
+dnl
+dnl History:
+dnl
+dnl Modified by cmetz for OPIE 2.3. Removed redundant memset/memcpy.
+dnl Changed ls -g test around. Changed logindevperm/fbtab defines.
+dnl Added check for /etc/environment and /etc/src.sh. Check for
+dnl /var/adm/sulog. Check for {get,put}utxline, provide libmissing
+dnl versionf of {get,put}utline. Added --enable option for anonymous
+dnl FTP. Got rid of a few unneeded checks. Check for functions only
+dnl used by libmissing only if the replacement function that needs
+dnl them is itself needed.
+dnl Modified by cmetz for OPIE 2.22. Check for Solaris drain bamaged ls.
+dnl Check for setlogin(). Removed duplicate checks for some funcs.
+dnl Modified by cmetz for OPIE 2.21. Filename must be in utmp[x]/wtmp[x]
+dnl defines.
+dnl Modified by cmetz for OPIE 2.2. Misc changes. Changed for libmissing
+dnl support and building its target object list. Changed to support
+dnl FUNCTION declaration et al. Added a LOT of checks and a LOT of
+dnl fixes.
+dnl Created at NRL for OPIE 2.1.
+
+AC_INIT(README)
+AC_CONFIG_HEADER(config.h)
+AC_ARG_ENABLE(access-file, [ --enable-access-file=PATH Use the OPIE access file PATH as a transition aid], AC_DEFINE_UNQUOTED(PATH_ACCESS_FILE, "$enable_access_file") echo "Using the access file in $enable_access_file -- don't say we didn't warn you!")
+AC_ARG_ENABLE(anonymous-ftp, [ --enable-anonymous-ftp Enable anonymous FTP support], AC_DEFINE(DOANONYMOUS) echo "Enabling anonymous FTP support in ftp -- don't say we didn't warn you!")
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_LN_S
+AC_PROG_RANLIB
+AC_PROG_YACC
+
+AC_AIX
+AC_ISC_POSIX
+AC_MINIX
+
+AC_C_CROSS
+
+dnl We'd put PATH in these checks, but it turns out that autoconf doesn't
+dnl work as documented when it comes to the colon separator...
+
+AC_PATH_PROG(CHOWN, chown, /bin/chown, /usr/bin /bin /usr/sbin /sbin /usr/etc /etc)
+
+AC_PATH_PROG(SU, su, /bin/su, /usr/bin /bin)
+AC_PATH_PROG(ALT_SU, su,, /usr/sbin /sbin)
+
+AC_PATH_PROG(SCHEME, scheme,, /usr/lib/iaf/scheme)
+AC_PATH_PROG(LOGIN, login, /bin/login, /usr/bin /bin)
+dnl AC_DEFINE_UNQUOTED(PATH_LOGIN, "$LOGIN")
+
+if test ! -z "$SCHEME";
+then
+ LOGIN="$SCHEME";
+fi
+
+AC_PATH_PROG(FTPD, ftpd,, /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin)
+AC_PATH_PROG(INFTPD, in.ftpd,, /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin)
+
+if test -z "$FTPD"
+then
+ if test ! -z "$INFTPD"
+ then
+ FTPD="$INFTPD"
+ fi
+fi
+
+AC_MSG_CHECKING(for default PATH entries)
+default_path=""
+save_IFS="$IFS"
+IFS=" "
+for i in /usr/bin /bin /usr/ucb /usr/sbin /usr/bsd /sbin /usr/bin/X11 /etc /usr/local/X11/bin /usr/X11R6/bin /your-system-is-broken
+do
+ IFS=":"
+ for j in $PATH
+ do
+ if test "$i" = "$j"
+ then
+ if test -d "$i"
+ then
+ if test -z "$default_path"
+ then
+ default_path="$i"
+ else
+ default_path="$default_path:$i"
+ fi
+ fi
+ fi
+ done
+ IFS=" "
+done
+AC_DEFINE_UNQUOTED(DEFAULT_PATH, "$default_path")
+AC_MSG_RESULT($default_path)
+
+AC_MSG_CHECKING(for test -e flag)
+if sh config.testeflag
+then
+ result=yes
+ EXISTS="-e"
+else
+ result=no
+ EXISTS="-f"
+fi
+AC_SUBST(EXISTS)
+AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(for mkdir -p flag)
+if test -d config.tmpdir
+then
+ rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null
+ rmdir config.tmpdir/foo >/dev/null 2>/dev/null
+ rmdir config.tmpdir >/dev/null 2>/dev/null
+fi
+
+result=no
+if mkdir -p config.tmpdir/foo/bar >/dev/null 2>/dev/null
+then
+ if test -d config.tmpdir
+ then
+ if test -d config.tmpdir/foo
+ then
+ if test -d config.tmpdir/foo/bar
+ then
+ result=yes
+ rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null
+ fi
+ rmdir config.tmpdir/foo >/dev/null 2>/dev/null
+ fi
+ rmdir config.tmpdir >/dev/null 2>/dev/null
+ fi
+fi
+
+if test "$result" = yes
+then
+ MKDIR="mkdir -p"
+else
+ MKDIR="mkdir"
+fi
+AC_SUBST(MKDIR)
+AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(for ls group field)
+lsg=`/bin/ls -ldg / | wc -w | awk '{print $1}'`;
+ls=`/bin/ls -ld / | wc -w | awk '{print $1}'`;
+result="no"
+if test $ls = 9;
+then
+ result="yes"
+else
+ if test "$ls" = 8 -a "$lsg" = 9;
+ then
+ result="yes, with -g"
+ AC_DEFINE(HAVE_LS_G_FLAG)
+ fi
+fi
+AC_MSG_RESULT($result)
+
+dnl Checks for various system characteristics
+AC_MSG_CHECKING(for /etc/default/login)
+if test $EXISTS /etc/default/login
+then
+ result=yes
+ AC_DEFINE(HAVE_ETC_DEFAULT_LOGIN)
+else
+ result=no
+fi
+AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(for /etc/securetty)
+if test $EXISTS /etc/securetty
+then
+ result=yes
+ AC_DEFINE(HAVE_SECURETTY)
+else
+ result=no
+fi
+AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(for /etc/logindevperm)
+if test $EXISTS /etc/logindevperm
+then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LOGIN_PERMFILE, "/etc/logindevperm")
+else
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING(for /etc/fbtab)
+ if test $EXISTS /etc/fbtab
+ then
+ result=yes
+ AC_DEFINE(HAVE_LOGIN_PERMFILE, "/etc/fbtab")
+ else
+ result=no
+ fi
+ AC_MSG_RESULT($result)
+fi
+
+AC_MSG_CHECKING(for /etc/environment)
+if test $EXISTS /etc/environment
+then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LOGIN_ENVFILE, "/etc/environment")
+else
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING(for /etc/src.sh)
+ if test $EXISTS /etc/src.sh
+ then
+ result=yes
+ AC_DEFINE(HAVE_LOGIN_ENVFILE, "/etc/src.sh")
+ else
+ result=no
+ fi
+ AC_MSG_RESULT($result)
+fi
+
+AC_MSG_CHECKING(for /etc/shadow)
+if test $EXISTS /etc/shadow
+then
+ result=yes
+ AC_DEFINE(HAVE_ETC_SHADOW)
+else
+ result=no
+fi
+AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(for /var/adm/sulog)
+if test $EXISTS /var/adm/sulog
+then
+ result=yes
+ AC_DEFINE(HAVE_SULOG)
+else
+ result=no
+fi
+AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(mail spool location)
+mail_spool=""
+for i in /var/mail /usr/mail /var/spool/mail /usr/spool/mail
+do
+ if test -d $i
+ then
+ mail_spool="$i"
+ fi
+done
+if test -z "$mail_spool"
+then
+ result="not found"
+else
+ result="$mail_spool"
+ AC_DEFINE_UNQUOTED(PATH_MAIL, "$mail_spool")
+fi
+AC_MSG_RESULT($result)
+
+dnl AC_MSG_CHECKING(where your system puts the utmp file)
+dnl utmp_path=""
+dnl for i in /var/run /var/adm /usr/adm /etc
+dnl do
+dnl if test $EXISTS $i/utmp
+dnl then
+dnl utmp_path="$i"
+dnl fi
+dnl done
+dnl if test -z "$utmp_path"
+dnl then
+dnl result="not found"
+dnl else
+dnl result="$utmp_path"
+dnl AC_DEFINE_UNQUOTED(PATH_UTMP_AC, "$utmp_path/utmp")
+dnl fi
+dnl AC_MSG_RESULT($result)
+
+dnl AC_MSG_CHECKING(where your system puts the wtmp file)
+dnl wtmp_path=""
+dnl for i in /var/run /var/adm /usr/adm /etc
+dnl do
+dnl if test $EXISTS $i/wtmp
+dnl then
+dnl wtmp_path="$i"
+dnl fi
+dnl done
+dnl if test -z "$wtmp_path"
+dnl then
+dnl result="not found"
+dnl else
+dnl result="$wtmp_path"
+dnl AC_DEFINE_UNQUOTED(PATH_WTMP_AC, "$wtmp_path/wtmp")
+dnl fi
+dnl AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(whether the system profile displays the motd)
+result=no
+if test $EXISTS /etc/profile
+then
+ if grep motd /etc/profile >/dev/null 2>/dev/null
+ then
+ result=yes
+ fi
+fi
+if test "$result" = yes
+then
+ AC_DEFINE(HAVE_MOTD_IN_PROFILE)
+fi
+AC_MSG_RESULT($result)
+
+AC_MSG_CHECKING(whether the system profile checks for mail)
+result=no
+if test $EXISTS /etc/profile
+then
+ if grep 'mail\.' /etc/profile >/dev/null 2>/dev/null
+ then
+ result=yes
+ fi
+fi
+if test "$result" = yes
+then
+ AC_DEFINE(HAVE_MAILCHECK_IN_PROFILE)
+fi
+AC_MSG_RESULT($result)
+
+dnl Random checks
+AC_C_CONST
+
+AC_MSG_CHECKING(to see if your compiler can handle void arguments)
+AC_TRY_COMPILE(foo(void) { },, AC_DEFINE(HAVE_VOIDARG) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(to see if your compiler can handle void return values)
+AC_TRY_COMPILE(void foo() { },, AC_DEFINE(HAVE_VOIDRET) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(to see if your compiler can handle void pointers)
+AC_TRY_COMPILE(foo() { void *bar = (void *)0x42; bar = bar + 1; },, AC_DEFINE(HAVE_VOIDPTR) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(to see if your compiler can handle ANSI argument lists)
+AC_TRY_COMPILE(int foo(int bar, int baz) { return 0; },, AC_DEFINE(HAVE_ANSIDECL) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(to see if your compiler can handle ANSI prototypes)
+AC_TRY_COMPILE(extern int foo(int, int);,, AC_DEFINE(HAVE_ANSIPROTO) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(to see if your compiler can handle ANSI variable arguments)
+AC_TRY_COMPILE([#include <stdarg.h>
+int foo(int arg, ...) {
+ va_list ap;
+ va_start(ap, arg);
+ va_end(ap);
+ return 0;
+}],, AC_DEFINE(HAVE_ANSISTDARG) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(to see if you have an ANSI-style sprintf)
+AC_TRY_RUN([#include <stdio.h>
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ char buf[5];
+ int i = 2;
+ i += sprintf(buf, "1234");
+ return (i == 6) ? 0 : -1;
+}], AC_DEFINE(HAVE_ANSISPRINTF) AC_MSG_RESULT(yes), AC_MSG_RESULT(no), AC_MSG_RESULT(no))
+
+dnl Checks for libraries.
+AC_CHECK_LIB(crypt, crypt)
+AC_CHECK_LIB(nsl, gethostname)
+AC_CHECK_LIB(posix, main)
+AC_CHECK_LIB(socket, socket)
+
+dnl Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(crypt.h fcntl.h limits.h termios.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h paths.h shadow.h signal.h sys/signal.h lastlog.h sys/utsname.h pwd.h sys/param.h string.h stdlib.h utmpx.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+dnl AC_TYPE_UID_T
+dnl AC_TYPE_OFF_T
+dnl AC_TYPE_PID_T
+dnl AC_STRUCT_ST_BLKSIZE
+dnl AC_STRUCT_TM
+
+AC_MSG_CHECKING(for ut_pid in struct utmp)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmp.h>], [struct utmp foo; return (int)foo.ut_pid;], AC_DEFINE(HAVE_UT_PID) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+AC_MSG_CHECKING(for ut_type in struct utmp)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmp.h>], [struct utmp foo; return (int)foo.ut_type;], AC_DEFINE(HAVE_UT_TYPE) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+AC_MSG_CHECKING(for ut_name in struct utmp)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <utmp.h>], [struct utmp foo; return (int)foo.ut_name[0];], AC_DEFINE(HAVE_UT_NAME) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+dnl AC_MSG_CHECKING(for ut_user in struct utmp)
+dnl AC_TRY_COMPILE([#include <sys/types.h>
+dnl #include <utmp.h>], [struct utmp foo; return (int)foo.ut_user[0];], AC_DEFINE(HAVE_UT_USER) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+AC_DEFINE(HAVE_UT_HOST)
+
+dnl Checks for library functions.
+dnl AC_PROG_GCC_TRADITIONAL
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS(gettimeofday socket strftime strstr setpriority seteuid setreuid setegid setregid setresuid setresgid getttynam sysconf setvbuf getspent endspent setgroups getgroups fpurge setlogin lstat getutxline pututxline)
+
+dnl Libmissing...
+AC_FUNC_MEMCMP
+AC_FUNC_ALLOCA
+AC_REPLACE_FUNCS(getusershell sigaddset sigemptyset strerror strncasecmp)
+MISSING="$LIBOBJS $ALLOCA "
+AC_CHECK_FUNC(atexit,, MISSING="${MISSING}atexit.o ")
+AC_CHECK_FUNC(entutent,, MISSING="${MISSING}endutent.o ")
+AC_CHECK_FUNC(memcpy,, MISSING="${MISSING}memcpy.o "; AC_CHECK_FUNCS(bcopy))
+AC_CHECK_FUNC(memset,, MISSING="${MISSING}memset.o "; AC_CHECK_FUNCS(bzero))
+AC_CHECK_FUNC(getcwd,, MISSING="${MISSING}getcwd.o "; AC_CHECK_FUNCS(getwd))
+AC_CHECK_FUNC(getenv, AC_DEFINE(HAVE_GETENV), MISSING="${MISSING}env.o ")
+AC_CHECK_FUNC(getutline,, MISSING="${MISSING}getutline.o "; AC_CHECK_FUNCS(ttyslot))
+AC_CHECK_FUNC(pututline,, MISSING="${MISSING}pututline.o "; AC_CHECK_FUNCS(ttyslot))
+AC_CHECK_FUNC(setenv, AC_DEFINE(HAVE_SETENV), MISSING="${MISSING}env.o ")
+AC_CHECK_FUNC(sigprocmask,, MISSING="${MISSING}sigprocmask.o "; AC_CHECK_FUNCS(sigblock sigsetmask))
+AC_CHECK_FUNC(strchr,, MISSING="${MISSING}strchr.o "; AC_CHECK_FUNCS(index))
+AC_CHECK_FUNC(strrchr,, MISSING="${MISSING}strrchr.o "; AC_CHECK_FUNCS(rindex))
+AC_CHECK_FUNC(sysconf,, MISSING="${MISSING}sysconf.o "; AC_CHECK_FUNCS(getdtablesize))
+AC_CHECK_FUNC(uname,, MISSING="${MISSING}uname.o "; AC_CHECK_FUNCS(gethostname))
+AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV), MISSING="${MISSING}env.o ")
+AC_SUBST(MISSING)
+
+AC_MSG_CHECKING(for nonstandard gettimeofday)
+AC_TRY_COMPILE([
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+],
+[struct timeval tv;
+gettimeofday(&tv, NULL)], AC_MSG_RESULT(no), AC_MSG_RESULT(maybe) AC_TRY_COMPILE([
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+],
+[struct timeval tv;
+gettimeofday(&tv)], AC_DEFINE(HAVE_ONE_ARG_GETTIMEOFDAY) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)))
+
+# Munge out LOCALBIN and LOCALMAN in canonical (no bletch) form
+AC_OUTPUT(configure.munger libmissing/Makefile libopie/Makefile Makefile.munge:Makefile.in)
+sh configure.munger
diff --git a/contrib/opie/configure.munger.in b/contrib/opie/configure.munger.in
new file mode 100644
index 0000000..25f5ebf
--- /dev/null
+++ b/contrib/opie/configure.munger.in
@@ -0,0 +1,16 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+mandir=@mandir@
+
+LOCALBIN=$bindir
+LOCALMAN=$mandir
+
+echo ""
+echo "Binaries are going to be installed into $LOCALBIN,"
+echo "Manual pages are going to be installed into $LOCALMAN."
+echo ""
+echo "creating Makefile"
+cat Makefile.munge | sed s:@LOCALMAN@:$LOCALMAN:g | sed s:@LOCALBIN@:$LOCALBIN:g > Makefile
+echo ""
+echo "Have you read the README file?"
diff --git a/contrib/opie/ftpcmd.y b/contrib/opie/ftpcmd.y
new file mode 100644
index 0000000..10ef24f
--- /dev/null
+++ b/contrib/opie/ftpcmd.y
@@ -0,0 +1,1286 @@
+/* ftpcmd.y: yacc parser for the FTP daemon.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Moved LS_COMMAND here.
+ Modified by cmetz for OPIE 2.2. Fixed a *lot* of warnings.
+ Use FUNCTION declaration et al. Removed useless strings.
+ Changed some char []s to char *s. Deleted comment address.
+ Changed tmpline references to be more pure-pointer
+ references. Changed tmpline declaration back to char [].
+ Modified at NRL for OPIE 2.1. Minor changes for autoconf.
+ Modified at NRL for OPIE 2.01. Added forward declaration for sitetab[]
+ -- fixes problems experienced by bison users. Merged in new
+ PORT attack fixes from Hobbit.
+ Modified at NRL for OPIE 2.0.
+ Originally from BSD.
+*/
+/*
+ * Copyright (c) 1985, 1988 Regents of the University of California.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ftpcmd.y 5.24 (Berkeley) 2/25/91
+ */
+
+/*
+ * Grammar for FTP commands.
+ * See RFC 959.
+ */
+
+%{
+#include "opie_cfg.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/ftp.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <syslog.h>
+#if TM_IN_SYS_TIME
+#include <sys/time.h>
+#else /* TM_IN_SYS_TIME */
+#include <time.h>
+#endif /* TM_IN_SYS_TIME */
+#include <pwd.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "opie.h"
+
+#if HAVE_LS_G_FLAG
+#define LS_COMMAND "/bin/ls -lgA"
+#else /* HAVE_LS_G_FLAG */
+#define LS_COMMAND "/bin/ls -lA"
+#endif /* HAVE_LS_G_FLAG */
+
+extern struct sockaddr_in data_dest;
+extern struct sockaddr_in his_addr;
+extern int logged_in;
+extern struct passwd *pw;
+extern int guest;
+extern int type;
+extern int form;
+extern int debug;
+extern int timeout;
+extern int maxtimeout;
+extern int pdata;
+extern char *remotehost;
+extern char *proctitle;
+extern char *globerr;
+extern int usedefault;
+extern int transflag;
+extern char tmpline[];
+char **ftpglob();
+
+VOIDRET dologout __P((int));
+VOIDRET upper __P((char *));
+VOIDRET nack __P((char *));
+VOIDRET opiefatal __P((char *));
+
+VOIDRET pass __P((char *));
+int user __P((char *));
+VOIDRET passive __P((void));
+VOIDRET retrieve __P((char *, char *));
+VOIDRET store __P((char *, char *, int));
+VOIDRET send_file_list __P((char *));
+VOIDRET statfilecmd __P((char *));
+VOIDRET statcmd __P((void));
+VOIDRET delete __P((char *));
+VOIDRET renamecmd __P((char *, char *));
+VOIDRET cwd __P((char *));
+VOIDRET makedir __P((char *));
+VOIDRET removedir __P((char *));
+VOIDRET pwd __P((void));
+
+VOIDRET sizecmd __P((char *));
+
+off_t restart_point;
+
+static int cmd_type;
+static int cmd_form;
+static int cmd_bytesz;
+static unsigned short cliport = 0;
+char cbuf[512];
+char *fromname;
+
+struct tab {
+ char *name;
+ short token;
+ short state;
+ short implemented; /* 1 if command is implemented */
+ char *help;
+};
+
+VOIDRET help __P((struct tab *, char *));
+
+struct tab cmdtab[], sitetab[];
+
+%}
+
+%token
+ A B C E F I
+ L N P R S T
+
+ SP CRLF COMMA STRING NUMBER
+
+ USER PASS ACCT REIN QUIT PORT
+ PASV TYPE STRU MODE RETR STOR
+ APPE MLFL MAIL MSND MSOM MSAM
+ MRSQ MRCP ALLO REST RNFR RNTO
+ ABOR DELE CWD LIST NLST SITE
+ STAT HELP NOOP MKD RMD PWD
+ CDUP STOU SMNT SYST SIZE MDTM
+
+ UMASK IDLE CHMOD
+
+ LEXERR
+
+%start cmd_list
+
+%%
+
+cmd_list: /* empty */
+ | cmd_list cmd
+ = {
+ fromname = (char *) 0;
+ restart_point = (off_t) 0;
+ }
+ | cmd_list rcmd
+ ;
+
+cmd: USER SP username CRLF
+ = {
+ user((char *) $3);
+ free((char *) $3);
+ }
+ | PASS SP password CRLF
+ = {
+ pass((char *) $3);
+ free((char *) $3);
+ }
+ | PORT check_login SP host_port CRLF
+ = {
+ usedefault = 0;
+ if (pdata >= 0) {
+ (void) close(pdata);
+ pdata = -1;
+ }
+/* H* port fix, part B: admonish the twit.
+ Also require login before PORT works */
+ if ($2) {
+ if ((cliport > 1023) && (data_dest.sin_addr.s_addr > 0)) {
+ reply(200, "PORT command successful.");
+ } else {
+ syslog (LOG_WARNING, "refused %s from %s",
+ cbuf, remotehost);
+ reply(500, "You've GOT to be joking.");
+ }
+ }
+ }
+/* | PASV CRLF
+ = {
+ passive();
+ } */
+ | PASV check_login CRLF
+ = {
+/* Require login for PASV, too. This actually fixes a bug -- telnet to an
+ unfixed wu-ftpd and type PASV first off, and it crashes! */
+ if ($2) {
+ passive();
+ }
+ }
+ | TYPE SP type_code CRLF
+ = {
+ switch (cmd_type) {
+
+ case TYPE_A:
+ if (cmd_form == FORM_N) {
+ reply(200, "Type set to A.");
+ type = cmd_type;
+ form = cmd_form;
+ } else
+ reply(504, "Form must be N.");
+ break;
+
+ case TYPE_E:
+ reply(504, "Type E not implemented.");
+ break;
+
+ case TYPE_I:
+ reply(200, "Type set to I.");
+ type = cmd_type;
+ break;
+
+ case TYPE_L:
+#if NBBY == 8
+ if (cmd_bytesz == 8) {
+ reply(200,
+ "Type set to L (byte size 8).");
+ type = cmd_type;
+ } else
+ reply(504, "Byte size must be 8.");
+#else /* NBBY == 8 */
+ UNIMPLEMENTED for NBBY != 8
+#endif /* NBBY == 8 */
+ }
+ }
+ | STRU SP struct_code CRLF
+ = {
+ switch ($3) {
+
+ case STRU_F:
+ reply(200, "STRU F ok.");
+ break;
+
+ default:
+ reply(504, "Unimplemented STRU type.");
+ }
+ }
+ | MODE SP mode_code CRLF
+ = {
+ switch ($3) {
+
+ case MODE_S:
+ reply(200, "MODE S ok.");
+ break;
+
+ default:
+ reply(502, "Unimplemented MODE type.");
+ }
+ }
+ | ALLO SP NUMBER CRLF
+ = {
+ reply(202, "ALLO command ignored.");
+ }
+ | ALLO SP NUMBER SP R SP NUMBER CRLF
+ = {
+ reply(202, "ALLO command ignored.");
+ }
+ | RETR check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ retrieve((char *) 0, (char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+ | STOR check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ store((char *) $4, "w", 0);
+ if ($4)
+ free((char *) $4);
+ }
+ | APPE check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ store((char *) $4, "a", 0);
+ if ($4)
+ free((char *) $4);
+ }
+ | NLST check_login CRLF
+ = {
+ if ($2)
+ send_file_list(".");
+ }
+ | NLST check_login SP STRING CRLF
+ = {
+ if ($2 && $4)
+ send_file_list((char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+ | LIST check_login CRLF
+ = {
+ if ($2)
+ retrieve(LS_COMMAND, "");
+ }
+ | LIST check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ {
+ char buffer[sizeof(LS_COMMAND)+3];
+ strcpy(buffer, LS_COMMAND);
+ strcat(buffer, " %s");
+ retrieve(buffer, (char *) $4);
+ }
+ if ($4)
+ free((char *) $4);
+ }
+ | STAT check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ statfilecmd((char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+ | STAT CRLF
+ = {
+ statcmd();
+ }
+ | DELE check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ delete((char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+ | RNTO SP pathname CRLF
+ = {
+ if (fromname) {
+ renamecmd(fromname, (char *) $3);
+ free(fromname);
+ fromname = (char *) 0;
+ } else {
+ reply(503, "Bad sequence of commands.");
+ }
+ free((char *) $3);
+ }
+ | ABOR CRLF
+ = {
+ reply(225, "ABOR command successful.");
+ }
+ | CWD check_login CRLF
+ = {
+ if ($2)
+ cwd(pw->pw_dir);
+ }
+ | CWD check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ cwd((char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+ | HELP CRLF
+ = {
+ help(cmdtab, (char *) 0);
+ }
+ | HELP SP STRING CRLF
+ = {
+ register char *cp = (char *)$3;
+
+ if (strncasecmp(cp, "SITE", 4) == 0) {
+ cp = (char *)$3 + 4;
+ if (*cp == ' ')
+ cp++;
+ if (*cp)
+ help(sitetab, cp);
+ else
+ help(sitetab, (char *) 0);
+ } else
+ help(cmdtab, (char *) $3);
+ }
+ | NOOP CRLF
+ = {
+ reply(200, "NOOP command successful.");
+ }
+ | MKD check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ makedir((char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+ | RMD check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ removedir((char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+ | PWD check_login CRLF
+ = {
+ if ($2)
+ pwd();
+ }
+ | CDUP check_login CRLF
+ = {
+ if ($2)
+ cwd("..");
+ }
+ | SITE SP HELP CRLF
+ = {
+ help(sitetab, (char *) 0);
+ }
+ | SITE SP HELP SP STRING CRLF
+ = {
+ help(sitetab, (char *) $5);
+ }
+ | SITE SP UMASK check_login CRLF
+ = {
+ int oldmask;
+
+ if ($4) {
+ oldmask = umask(0);
+ (void) umask(oldmask);
+ reply(200, "Current UMASK is %03o", oldmask);
+ }
+ }
+ | SITE SP UMASK check_login SP octal_number CRLF
+ = {
+ int oldmask;
+
+ if ($4) {
+ if (($6 == -1) || ($6 > 0777)) {
+ reply(501, "Bad UMASK value");
+ } else {
+ oldmask = umask($6);
+ reply(200,
+ "UMASK set to %03o (was %03o)",
+ $6, oldmask);
+ }
+ }
+ }
+ | SITE SP CHMOD check_login SP octal_number SP pathname CRLF
+ = {
+ if ($4 && $8) {
+ if ($6 > 0777)
+ reply(501,
+ "CHMOD: Mode value must be between 0 and 0777");
+ else if (chmod((char *) $8, $6) < 0)
+ perror_reply(550, (char *) $8);
+ else
+ reply(200, "CHMOD command successful.");
+ }
+ if ($8)
+ free((char *) $8);
+ }
+ | SITE SP IDLE CRLF
+ = {
+ reply(200,
+ "Current IDLE time limit is %d seconds; max %d",
+ timeout, maxtimeout);
+ }
+ | SITE SP IDLE SP NUMBER CRLF
+ = {
+ if ($5 < 30 || $5 > maxtimeout) {
+ reply(501,
+ "Maximum IDLE time must be between 30 and %d seconds",
+ maxtimeout);
+ } else {
+ timeout = $5;
+ (void) alarm((unsigned) timeout);
+ reply(200,
+ "Maximum IDLE time set to %d seconds",
+ timeout);
+ }
+ }
+ | STOU check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ store((char *) $4, "w", 1);
+ if ($4)
+ free((char *) $4);
+ }
+ | SYST CRLF
+ = {
+#ifdef unix
+#ifdef BSD
+ reply(215, "UNIX Type: L%d Version: BSD-%d",
+ NBBY, BSD);
+#else /* BSD */
+ reply(215, "UNIX Type: L%d", NBBY);
+#endif /* BSD */
+#else /* unix */
+ reply(215, "UNKNOWN Type: L%d", NBBY);
+#endif /* unix */
+ }
+
+ /*
+ * SIZE is not in RFC959, but Postel has blessed it and
+ * it will be in the updated RFC.
+ *
+ * Return size of file in a format suitable for
+ * using with RESTART (we just count bytes).
+ */
+ | SIZE check_login SP pathname CRLF
+ = {
+ if ($2 && $4)
+ sizecmd((char *) $4);
+ if ($4)
+ free((char *) $4);
+ }
+
+ /*
+ * MDTM is not in RFC959, but Postel has blessed it and
+ * it will be in the updated RFC.
+ *
+ * Return modification time of file as an ISO 3307
+ * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx
+ * where xxx is the fractional second (of any precision,
+ * not necessarily 3 digits)
+ */
+ | MDTM check_login SP pathname CRLF
+ = {
+ if ($2 && $4) {
+ struct stat stbuf;
+ if (stat((char *) $4, &stbuf) < 0)
+ perror_reply(550, (char *) $4);
+ else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
+ reply(550, "%s: not a plain file.",
+ (char *) $4);
+ } else {
+ register struct tm *t;
+ struct tm *gmtime();
+ t = gmtime(&stbuf.st_mtime);
+ reply(213,
+ "19%02d%02d%02d%02d%02d%02d",
+ t->tm_year, t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ }
+ }
+ if ($4)
+ free((char *) $4);
+ }
+ | QUIT CRLF
+ = {
+ reply(221, "Goodbye.");
+ dologout(0);
+ }
+ | error CRLF
+ = {
+ yyerrok;
+ }
+ ;
+rcmd: RNFR check_login SP pathname CRLF
+ = {
+ char *renamefrom();
+
+ restart_point = (off_t) 0;
+ if ($2 && $4) {
+ fromname = renamefrom((char *) $4);
+ if (fromname == (char *) 0 && $4) {
+ free((char *) $4);
+ }
+ }
+ }
+ | REST SP byte_size CRLF
+ = {
+ long atol();
+
+ fromname = (char *) 0;
+ restart_point = $3;
+ reply(350, "Restarting at %ld. %s", restart_point,
+ "Send STORE or RETRIEVE to initiate transfer.");
+ }
+ ;
+
+username: STRING
+ ;
+
+password: /* empty */
+ = {
+ *(char **)&($$) = (char *)calloc(1, sizeof(char));
+ }
+ | STRING
+ ;
+
+byte_size: NUMBER
+ ;
+
+host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA
+ NUMBER COMMA NUMBER
+ = {
+ register char *a, *p;
+
+ a = (char *)&data_dest.sin_addr;
+ a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7;
+
+/* H* port fix, part A-1: Check the args against the client addr */
+ p = (char *)&his_addr.sin_addr;
+ if (memcmp (a, p, sizeof (data_dest.sin_addr)))
+ memset (a, 0, sizeof (data_dest.sin_addr)); /* XXX */
+
+ p = (char *)&data_dest.sin_port;
+
+/* H* port fix, part A-2: only allow client ports in "user space" */
+ p[0] = 0; p[1] = 0;
+ cliport = ($9 << 8) + $11;
+ if (cliport > 1023) {
+ p[0] = $9; p[1] = $11;
+ }
+
+ p[0] = $9; p[1] = $11;
+ data_dest.sin_family = AF_INET;
+ }
+ ;
+
+form_code: N
+ = {
+ $$ = FORM_N;
+ }
+ | T
+ = {
+ $$ = FORM_T;
+ }
+ | C
+ = {
+ $$ = FORM_C;
+ }
+ ;
+
+type_code: A
+ = {
+ cmd_type = TYPE_A;
+ cmd_form = FORM_N;
+ }
+ | A SP form_code
+ = {
+ cmd_type = TYPE_A;
+ cmd_form = $3;
+ }
+ | E
+ = {
+ cmd_type = TYPE_E;
+ cmd_form = FORM_N;
+ }
+ | E SP form_code
+ = {
+ cmd_type = TYPE_E;
+ cmd_form = $3;
+ }
+ | I
+ = {
+ cmd_type = TYPE_I;
+ }
+ | L
+ = {
+ cmd_type = TYPE_L;
+ cmd_bytesz = NBBY;
+ }
+ | L SP byte_size
+ = {
+ cmd_type = TYPE_L;
+ cmd_bytesz = $3;
+ }
+ /* this is for a bug in the BBN ftp */
+ | L byte_size
+ = {
+ cmd_type = TYPE_L;
+ cmd_bytesz = $2;
+ }
+ ;
+
+struct_code: F
+ = {
+ $$ = STRU_F;
+ }
+ | R
+ = {
+ $$ = STRU_R;
+ }
+ | P
+ = {
+ $$ = STRU_P;
+ }
+ ;
+
+mode_code: S
+ = {
+ $$ = MODE_S;
+ }
+ | B
+ = {
+ $$ = MODE_B;
+ }
+ | C
+ = {
+ $$ = MODE_C;
+ }
+ ;
+
+pathname: pathstring
+ = {
+ /*
+ * Problem: this production is used for all pathname
+ * processing, but only gives a 550 error reply.
+ * This is a valid reply in some cases but not in others.
+ */
+ if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) {
+ *(char **)&($$) = *ftpglob((char *) $1);
+ if (globerr != NULL) {
+ reply(550, globerr);
+/* $$ = NULL; */
+ $$ = 0;
+ }
+ free((char *) $1);
+ } else
+ $$ = $1;
+ }
+ ;
+
+pathstring: STRING
+ ;
+
+octal_number: NUMBER
+ = {
+ register int ret, dec, multby, digit;
+
+ /*
+ * Convert a number that was read as decimal number
+ * to what it would be if it had been read as octal.
+ */
+ dec = $1;
+ multby = 1;
+ ret = 0;
+ while (dec) {
+ digit = dec%10;
+ if (digit > 7) {
+ ret = -1;
+ break;
+ }
+ ret += digit * multby;
+ multby *= 8;
+ dec /= 10;
+ }
+ $$ = ret;
+ }
+ ;
+
+check_login: /* empty */
+ = {
+ if (logged_in)
+ $$ = 1;
+ else {
+ reply(530, "Please login with USER and PASS.");
+ $$ = 0;
+ }
+ }
+ ;
+
+%%
+
+extern jmp_buf errcatch;
+
+#define CMD 0 /* beginning of command */
+#define ARGS 1 /* expect miscellaneous arguments */
+#define STR1 2 /* expect SP followed by STRING */
+#define STR2 3 /* expect STRING */
+#define OSTR 4 /* optional SP then STRING */
+#define ZSTR1 5 /* SP then optional STRING */
+#define ZSTR2 6 /* optional STRING after SP */
+#define SITECMD 7 /* SITE command */
+#define NSTR 8 /* Number followed by a string */
+
+struct tab cmdtab[] = { /* In order defined in RFC 765 */
+ { "USER", USER, STR1, 1, "<sp> username" },
+ { "PASS", PASS, ZSTR1, 1, "<sp> password" },
+ { "ACCT", ACCT, STR1, 0, "(specify account)" },
+ { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
+ { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
+ { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
+ { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
+ { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
+ { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
+ { "STRU", STRU, ARGS, 1, "(specify file structure)" },
+ { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
+ { "RETR", RETR, STR1, 1, "<sp> file-name" },
+ { "STOR", STOR, STR1, 1, "<sp> file-name" },
+ { "APPE", APPE, STR1, 1, "<sp> file-name" },
+ { "MLFL", MLFL, OSTR, 0, "(mail file)" },
+ { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
+ { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
+ { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
+ { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
+ { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
+ { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
+ { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
+ { "REST", REST, ARGS, 1, "(restart command)" },
+ { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
+ { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
+ { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
+ { "DELE", DELE, STR1, 1, "<sp> file-name" },
+ { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
+ { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
+ { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
+ { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
+ { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
+ { "SYST", SYST, ARGS, 1, "(get type of operating system)" },
+ { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
+ { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
+ { "NOOP", NOOP, ARGS, 1, "" },
+ { "MKD", MKD, STR1, 1, "<sp> path-name" },
+ { "XMKD", MKD, STR1, 1, "<sp> path-name" },
+ { "RMD", RMD, STR1, 1, "<sp> path-name" },
+ { "XRMD", RMD, STR1, 1, "<sp> path-name" },
+ { "PWD", PWD, ARGS, 1, "(return current directory)" },
+ { "XPWD", PWD, ARGS, 1, "(return current directory)" },
+ { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
+ { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
+ { "STOU", STOU, STR1, 1, "<sp> file-name" },
+ { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
+ { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
+ { NULL, 0, 0, 0, 0 }
+};
+
+struct tab sitetab[] = {
+ { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
+ { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
+ { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
+ { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
+ { NULL, 0, 0, 0, 0 }
+};
+
+struct tab *lookup FUNCTION((p, cmd), register struct tab *p AND char *cmd)
+{
+
+ for (; p->name != NULL; p++)
+ if (strcmp(cmd, p->name) == 0)
+ return (p);
+ return (0);
+}
+
+#include <arpa/telnet.h>
+
+/*
+ * getline - a hacked up version of fgets to ignore TELNET escape codes.
+ */
+char *getline FUNCTION((s, n, iop), char *s AND int n AND FILE *iop)
+{
+ register c;
+ register char *cs;
+
+ cs = s;
+/* tmpline may contain saved command from urgent mode interruption */
+ for (c = 0; *(tmpline + c) && --n > 0; ++c) {
+ *cs++ = *(tmpline + c);
+ if (*(tmpline + c) == '\n') {
+ *cs++ = '\0';
+ if (debug)
+ syslog(LOG_DEBUG, "command: %s", s);
+ *tmpline = '\0';
+ return(s);
+ }
+ if (c == 0)
+ *tmpline = '\0';
+ }
+ while ((c = getc(iop)) != EOF) {
+ c &= 0377;
+ if (c == IAC) {
+ if ((c = getc(iop)) != EOF) {
+ c &= 0377;
+ switch (c) {
+ case WILL:
+ case WONT:
+ c = getc(iop);
+ printf("%c%c%c", IAC, DONT, 0377&c);
+ (void) fflush(stdout);
+ continue;
+ case DO:
+ case DONT:
+ c = getc(iop);
+ printf("%c%c%c", IAC, WONT, 0377&c);
+ (void) fflush(stdout);
+ continue;
+ case IAC:
+ break;
+ default:
+ continue; /* ignore command */
+ }
+ }
+ }
+ *cs++ = c;
+ if (--n <= 0 || c == '\n')
+ break;
+ }
+ if (c == EOF && cs == s)
+ return (NULL);
+ *cs++ = '\0';
+ if (debug)
+ syslog(LOG_DEBUG, "command: %s", s);
+ return (s);
+}
+
+static VOIDRET toolong FUNCTION((input), int input)
+{
+ time_t now;
+
+ reply(421, "Timeout (%d seconds): closing control connection.", timeout);
+ (void) time(&now);
+ syslog(LOG_INFO, "User %s timed out after %d seconds at %s",
+ (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
+ dologout(1);
+}
+
+int yylex FUNCTION_NOARGS
+{
+ static int cpos, state;
+ register char *cp, *cp2;
+ register struct tab *p;
+ int n;
+ char c, *copy();
+
+ for (;;) {
+ switch (state) {
+
+ case CMD:
+ (void) signal(SIGALRM, toolong);
+ (void) alarm((unsigned) timeout);
+ if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
+ reply(221, "You could at least say goodbye.");
+ dologout(0);
+ }
+ (void) alarm(0);
+#ifdef SETPROCTITLE
+ if (strncasecmp(cbuf, "PASS", 4) != NULL)
+ setproctitle("%s: %s", proctitle, cbuf);
+#endif /* SETPROCTITLE */
+ if ((cp = strchr(cbuf, '\r'))) {
+ *cp++ = '\n';
+ *cp = '\0';
+ }
+ if ((cp = strpbrk(cbuf, " \n")))
+ cpos = cp - cbuf;
+ if (cpos == 0)
+ cpos = 4;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ upper(cbuf);
+ p = lookup(cmdtab, cbuf);
+ cbuf[cpos] = c;
+ if (p != 0) {
+ if (p->implemented == 0) {
+ nack(p->name);
+ longjmp(errcatch,0);
+ /* NOTREACHED */
+ }
+ state = p->state;
+ *(char **)&yylval = p->name;
+ return (p->token);
+ }
+ break;
+
+ case SITECMD:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ return (SP);
+ }
+ cp = &cbuf[cpos];
+ if ((cp2 = strpbrk(cp, " \n")))
+ cpos = cp2 - cbuf;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ upper(cp);
+ p = lookup(sitetab, cp);
+ cbuf[cpos] = c;
+ if (p != 0) {
+ if (p->implemented == 0) {
+ state = CMD;
+ nack(p->name);
+ longjmp(errcatch,0);
+ /* NOTREACHED */
+ }
+ state = p->state;
+ *(char **)&yylval = p->name;
+ return (p->token);
+ }
+ state = CMD;
+ break;
+
+ case OSTR:
+ if (cbuf[cpos] == '\n') {
+ state = CMD;
+ return (CRLF);
+ }
+ /* FALLTHROUGH */
+
+ case STR1:
+ case ZSTR1:
+ dostr1:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ state = state == OSTR ? STR2 : ++state;
+ return (SP);
+ }
+ break;
+
+ case ZSTR2:
+ if (cbuf[cpos] == '\n') {
+ state = CMD;
+ return (CRLF);
+ }
+ /* FALLTHROUGH */
+
+ case STR2:
+ cp = &cbuf[cpos];
+ n = strlen(cp);
+ cpos += n - 1;
+ /*
+ * Make sure the string is nonempty and \n terminated.
+ */
+ if (n > 1 && cbuf[cpos] == '\n') {
+ cbuf[cpos] = '\0';
+ *(char **)&yylval = copy(cp);
+ cbuf[cpos] = '\n';
+ state = ARGS;
+ return (STRING);
+ }
+ break;
+
+ case NSTR:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ return (SP);
+ }
+ if (isdigit(cbuf[cpos])) {
+ cp = &cbuf[cpos];
+ while (isdigit(cbuf[++cpos]))
+ ;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ yylval = atoi(cp);
+ cbuf[cpos] = c;
+ state = STR1;
+ return (NUMBER);
+ }
+ state = STR1;
+ goto dostr1;
+
+ case ARGS:
+ if (isdigit(cbuf[cpos])) {
+ cp = &cbuf[cpos];
+ while (isdigit(cbuf[++cpos]))
+ ;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ yylval = atoi(cp);
+ cbuf[cpos] = c;
+ return (NUMBER);
+ }
+ switch (cbuf[cpos++]) {
+
+ case '\n':
+ state = CMD;
+ return (CRLF);
+
+ case ' ':
+ return (SP);
+
+ case ',':
+ return (COMMA);
+
+ case 'A':
+ case 'a':
+ return (A);
+
+ case 'B':
+ case 'b':
+ return (B);
+
+ case 'C':
+ case 'c':
+ return (C);
+
+ case 'E':
+ case 'e':
+ return (E);
+
+ case 'F':
+ case 'f':
+ return (F);
+
+ case 'I':
+ case 'i':
+ return (I);
+
+ case 'L':
+ case 'l':
+ return (L);
+
+ case 'N':
+ case 'n':
+ return (N);
+
+ case 'P':
+ case 'p':
+ return (P);
+
+ case 'R':
+ case 'r':
+ return (R);
+
+ case 'S':
+ case 's':
+ return (S);
+
+ case 'T':
+ case 't':
+ return (T);
+
+ }
+ break;
+
+ default:
+ opiefatal("Unknown state in scanner.");
+ }
+ yyerror((char *) 0);
+ state = CMD;
+ longjmp(errcatch,0);
+ }
+}
+
+VOIDRET upper FUNCTION((s), char *s)
+{
+ while (*s != '\0') {
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
+}
+
+char *copy FUNCTION((s), char *s)
+{
+ char *p;
+
+ p = malloc((unsigned) strlen(s) + 1);
+ if (p == NULL)
+ opiefatal("Ran out of memory.");
+ (void) strcpy(p, s);
+ return (p);
+}
+
+VOIDRET help FUNCTION((ctab, s), struct tab *ctab AND char *s)
+{
+ register struct tab *c;
+ register int width, NCMDS;
+ char *type;
+
+ if (ctab == sitetab)
+ type = "SITE ";
+ else
+ type = "";
+ width = 0, NCMDS = 0;
+ for (c = ctab; c->name != NULL; c++) {
+ int len = strlen(c->name);
+
+ if (len > width)
+ width = len;
+ NCMDS++;
+ }
+ width = (width + 8) &~ 7;
+ if (s == 0) {
+ register int i, j, w;
+ int columns, lines;
+
+ lreply(214, "The following %scommands are recognized %s.",
+ type, "(* =>'s unimplemented)");
+ columns = 76 / width;
+ if (columns == 0)
+ columns = 1;
+ lines = (NCMDS + columns - 1) / columns;
+ for (i = 0; i < lines; i++) {
+ printf(" ");
+ for (j = 0; j < columns; j++) {
+ c = ctab + j * lines + i;
+ printf("%s%c", c->name,
+ c->implemented ? ' ' : '*');
+ if (c + lines >= &ctab[NCMDS])
+ break;
+ w = strlen(c->name) + 1;
+ while (w < width) {
+ putchar(' ');
+ w++;
+ }
+ }
+ printf("\r\n");
+ }
+ (void) fflush(stdout);
+ return;
+ }
+ upper(s);
+ c = lookup(ctab, s);
+ if (c == (struct tab *)0) {
+ reply(502, "Unknown command %s.", s);
+ return;
+ }
+ if (c->implemented)
+ reply(214, "Syntax: %s%s %s", type, c->name, c->help);
+ else
+ reply(214, "%s%-*s\t%s; unimplemented.", type, width,
+ c->name, c->help);
+}
+
+VOIDRET sizecmd FUNCTION((filename), char *filename)
+{
+ switch (type) {
+ case TYPE_L:
+ case TYPE_I: {
+ struct stat stbuf;
+ if (stat(filename, &stbuf) < 0 ||
+ (stbuf.st_mode&S_IFMT) != S_IFREG)
+ reply(550, "%s: not a plain file.", filename);
+ else
+ reply(213, "%lu", stbuf.st_size);
+ break;}
+ case TYPE_A: {
+ FILE *fin;
+ register int c;
+ register long count;
+ struct stat stbuf;
+ fin = fopen(filename, "r");
+ if (fin == NULL) {
+ perror_reply(550, filename);
+ return;
+ }
+ if (fstat(fileno(fin), &stbuf) < 0 ||
+ (stbuf.st_mode&S_IFMT) != S_IFREG) {
+ reply(550, "%s: not a plain file.", filename);
+ (void) fclose(fin);
+ return;
+ }
+
+ count = 0;
+ while((c=getc(fin)) != EOF) {
+ if (c == '\n') /* will get expanded to \r\n */
+ count++;
+ count++;
+ }
+ (void) fclose(fin);
+
+ reply(213, "%ld", count);
+ break;}
+ default:
+ reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
+ }
+}
diff --git a/contrib/opie/glob.c b/contrib/opie/glob.c
new file mode 100644
index 0000000..342aa92
--- /dev/null
+++ b/contrib/opie/glob.c
@@ -0,0 +1,667 @@
+/* glob.c: The csh et al glob pattern matching routines.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Remove useless strings. Prototype right.
+ Modified at NRL for OPIE 2.0.
+ Originally from BSD.
+*/
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * C-shell glob for random programs.
+ */
+
+#include "opie_cfg.h"
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#include <sys/stat.h>
+
+#include <dirent.h>
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif /* HAVE_PWD_H */
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif /* HAVE_LIMITS_H */
+
+#include "opie.h"
+
+#ifndef NCARGS
+#define NCARGS 600
+#endif /* NCARGS */
+#define QUOTE 0200
+#define TRIM 0177
+#define eq(a,b) (strcmp((a),(b)) == (0))
+#define GAVSIZ (NCARGS/6)
+#define isdir(d) (((d.st_mode) & S_IFMT) == S_IFDIR)
+
+static char **gargv; /* Pointer to the (stack) arglist */
+static int gargc; /* Number args in gargv */
+static int gnleft;
+static short gflag;
+
+static int letter __P((register char));
+static int digit __P((register char));
+static int any __P((int, char *));
+static int blklen __P((register char **));
+VOIDRET blkfree __P((char **));
+static char *strspl __P((register char *, register char *));
+
+static int tglob __P((register char c));
+
+extern int errno;
+static char *strend __P((char *));
+
+static int globcnt;
+
+static char *globchars = "`{[*?";
+char *globerr = NULL;
+char *home = NULL;
+
+static char *gpath, *gpathp, *lastgpathp;
+static int globbed;
+static char *entp;
+static char **sortbas;
+
+static int amatch __P((char *p, char *s));
+static int execbrc __P((register char *p, register char *s));
+VOIDRET opiefatal __P((char *));
+char **copyblk __P((char **));
+
+static int match FUNCTION((s, p), char *s AND char *p)
+{
+ register int c;
+ register char *sentp;
+ char sglobbed = globbed;
+
+ if (*s == '.' && *p != '.')
+ return (0);
+ sentp = entp;
+ entp = s;
+ c = amatch(s, p);
+ entp = sentp;
+ globbed = sglobbed;
+ return (c);
+}
+
+
+static int Gmatch FUNCTION((s, p), register char *s AND register char *p)
+{
+ register int scc;
+ int ok, lc;
+ int c, cc;
+
+ for (;;) {
+ scc = *s++ & TRIM;
+ switch (c = *p++) {
+
+ case '[':
+ ok = 0;
+ lc = 077777;
+ while (cc = *p++) {
+ if (cc == ']') {
+ if (ok)
+ break;
+ return (0);
+ }
+ if (cc == '-') {
+ if (lc <= scc && scc <= *p++)
+ ok++;
+ } else
+ if (scc == (lc = cc))
+ ok++;
+ }
+ if (cc == 0)
+ if (ok)
+ p--;
+ else
+ return 0;
+ continue;
+
+ case '*':
+ if (!*p)
+ return (1);
+ for (s--; *s; s++)
+ if (Gmatch(s, p))
+ return (1);
+ return (0);
+
+ case 0:
+ return (scc == 0);
+
+ default:
+ if ((c & TRIM) != scc)
+ return (0);
+ continue;
+
+ case '?':
+ if (scc == 0)
+ return (0);
+ continue;
+
+ }
+ }
+}
+
+static VOIDRET Gcat FUNCTION((s1, s2), register char *s1 AND register char *s2)
+{
+ register int len = strlen(s1) + strlen(s2) + 1;
+
+ if (len >= gnleft || gargc >= GAVSIZ - 1)
+ globerr = "Arguments too long";
+ else {
+ gargc++;
+ gnleft -= len;
+ gargv[gargc] = 0;
+ gargv[gargc - 1] = strspl(s1, s2);
+ }
+}
+
+static VOIDRET addpath FUNCTION((c), char c)
+{
+
+ if (gpathp >= lastgpathp)
+ globerr = "Pathname too long";
+ else {
+ *gpathp++ = c;
+ *gpathp = 0;
+ }
+}
+
+static VOIDRET rscan FUNCTION((t, f), register char **t AND int (*f)__P((char)))
+{
+ register char *p, c;
+
+ while (p = *t++) {
+ if (f == tglob)
+ if (*p == '~')
+ gflag |= 2;
+ else
+ if (eq(p, "{") || eq(p, "{}"))
+ continue;
+ while (c = *p++)
+ (*f) (c);
+ }
+}
+
+static int tglob FUNCTION((c), register char c)
+{
+ if (any(c, globchars))
+ gflag |= c == '{' ? 2 : 1;
+ return (c);
+}
+
+static int letter FUNCTION((c), register char c)
+{
+ return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
+}
+
+static int digit FUNCTION((c), register char c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+static int any FUNCTION((c, s), int c AND char *s)
+{
+ while (*s)
+ if (*s++ == c)
+ return (1);
+ return (0);
+}
+
+static int blklen FUNCTION((av), register char **av)
+{
+ register int i = 0;
+
+ while (*av++)
+ i++;
+ return (i);
+}
+
+static char **blkcpy FUNCTION((oav, bv), char **oav AND register char **bv)
+{
+ register char **av = oav;
+
+ while (*av++ = *bv++)
+ continue;
+ return (oav);
+}
+
+VOIDRET blkfree FUNCTION((av0), char **av0)
+{
+ register char **av = av0;
+
+ while (*av)
+ free(*av++);
+}
+
+static char *strspl FUNCTION((cp, dp), register char *cp AND register char *dp)
+{
+ register char *ep = (char *) malloc((unsigned) (strlen(cp) +
+ strlen(dp) + 1));
+
+ if (ep == (char *) 0)
+ opiefatal("Out of memory");
+ strcpy(ep, cp);
+ strcat(ep, dp);
+ return (ep);
+}
+
+char **copyblk FUNCTION((v), char **v)
+{
+ register char **nv = (char **) malloc((unsigned) ((blklen(v) + 1) *
+ sizeof(char **)));
+
+ if (nv == (char **) 0)
+ opiefatal("Out of memory");
+
+ return (blkcpy(nv, v));
+}
+
+static char *strend FUNCTION((cp), register char *cp)
+{
+
+ while (*cp)
+ cp++;
+ return (cp);
+}
+
+/*
+ * Extract a home directory from the password file
+ * The argument points to a buffer where the name of the
+ * user whose home directory is sought is currently.
+ * We write the home directory of the user back there.
+ */
+static int gethdir FUNCTION((home), char *home)
+{
+ register struct passwd *pp = getpwnam(home);
+
+ if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
+ return (1);
+ strcpy(home, pp->pw_dir);
+ return (0);
+}
+
+static VOIDRET ginit FUNCTION((agargv), char **agargv)
+{
+ agargv[0] = 0;
+ gargv = agargv;
+ sortbas = agargv;
+ gargc = 0;
+ gnleft = NCARGS - 4;
+}
+
+static VOIDRET sort FUNCTION_NOARGS
+{
+ register char **p1, **p2, *c;
+ char **Gvp = &gargv[gargc];
+
+ p1 = sortbas;
+ while (p1 < Gvp - 1) {
+ p2 = p1;
+ while (++p2 < Gvp)
+ if (strcmp(*p1, *p2) > 0)
+ c = *p1, *p1 = *p2, *p2 = c;
+ p1++;
+ }
+ sortbas = Gvp;
+}
+
+static VOIDRET matchdir FUNCTION((pattern), char *pattern)
+{
+ struct stat stb;
+
+ register struct dirent *dp;
+
+ DIR *dirp;
+
+ dirp = opendir(*gpath == '\0' ? "." : gpath);
+ if (dirp == NULL) {
+ if (globbed)
+ return;
+ goto patherr2;
+ }
+#if !defined(linux)
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ goto patherr1;
+ if (!isdir(stb)) {
+ errno = ENOTDIR;
+ goto patherr1;
+ }
+#endif /* !defined(linux) */
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_ino == 0)
+ continue;
+ if (match(dp->d_name, pattern)) {
+ Gcat(gpath, dp->d_name);
+ globcnt++;
+ }
+ }
+ closedir(dirp);
+ return;
+
+patherr1:
+ closedir(dirp);
+patherr2:
+ globerr = "Bad directory components";
+}
+
+static VOIDRET expand FUNCTION((as), char *as)
+{
+ register char *cs;
+ register char *sgpathp, *oldcs;
+ struct stat stb;
+
+ sgpathp = gpathp;
+ cs = as;
+ if (*cs == '~' && gpathp == gpath) {
+ addpath('~');
+ for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
+ addpath(*cs++);
+ if (!*cs || *cs == '/') {
+ if (gpathp != gpath + 1) {
+ *gpathp = 0;
+ if (gethdir(gpath + 1))
+ globerr = "Unknown user name after ~";
+ strcpy(gpath, gpath + 1);
+ } else
+ strcpy(gpath, home);
+ gpathp = strend(gpath);
+ }
+ }
+ while (!any(*cs, globchars)) {
+ if (*cs == 0) {
+ if (!globbed)
+ Gcat(gpath, "");
+ else
+ if (stat(gpath, &stb) >= 0) {
+ Gcat(gpath, "");
+ globcnt++;
+ }
+ goto endit;
+ }
+ addpath(*cs++);
+ }
+ oldcs = cs;
+ while (cs > as && *cs != '/')
+ cs--, gpathp--;
+ if (*cs == '/')
+ cs++, gpathp++;
+ *gpathp = 0;
+ if (*oldcs == '{') {
+ execbrc(cs, ((char *) 0));
+ return;
+ }
+ matchdir(cs);
+endit:
+ gpathp = sgpathp;
+ *gpathp = 0;
+}
+
+static int execbrc FUNCTION((p, s), char *p AND char *s)
+{
+ char restbuf[BUFSIZ + 2];
+ register char *pe, *pm, *pl;
+ int brclev = 0;
+ char *lm, savec, *sgpathp;
+
+ for (lm = restbuf; *p != '{'; *lm++ = *p++)
+ continue;
+ for (pe = ++p; *pe; pe++)
+ switch (*pe) {
+
+ case '{':
+ brclev++;
+ continue;
+
+ case '}':
+ if (brclev == 0)
+ goto pend;
+ brclev--;
+ continue;
+
+ case '[':
+ for (pe++; *pe && *pe != ']'; pe++)
+ continue;
+ continue;
+ }
+pend:
+ brclev = 0;
+ for (pl = pm = p; pm <= pe; pm++)
+ switch (*pm & (QUOTE | TRIM)) {
+
+ case '{':
+ brclev++;
+ continue;
+
+ case '}':
+ if (brclev) {
+ brclev--;
+ continue;
+ }
+ goto doit;
+
+ case ',' | QUOTE:
+ case ',':
+ if (brclev)
+ continue;
+ doit:
+ savec = *pm;
+ *pm = 0;
+ strcpy(lm, pl);
+ strcat(restbuf, pe + 1);
+ *pm = savec;
+ if (s == 0) {
+ sgpathp = gpathp;
+ expand(restbuf);
+ gpathp = sgpathp;
+ *gpathp = 0;
+ } else
+ if (amatch(s, restbuf))
+ return (1);
+ sort();
+ pl = pm + 1;
+ if (brclev)
+ return (0);
+ continue;
+
+ case '[':
+ for (pm++; *pm && *pm != ']'; pm++)
+ continue;
+ if (!*pm)
+ pm--;
+ continue;
+ }
+ if (brclev)
+ goto doit;
+ return (0);
+}
+
+static VOIDRET acollect FUNCTION((as), register char *as)
+{
+ register int ogargc = gargc;
+
+ gpathp = gpath;
+ *gpathp = 0;
+ globbed = 0;
+ expand(as);
+ if (gargc != ogargc)
+ sort();
+}
+
+static VOIDRET collect FUNCTION((as), register char *as)
+{
+ if (eq(as, "{") || eq(as, "{}")) {
+ Gcat(as, "");
+ sort();
+ } else
+ acollect(as);
+}
+
+static int amatch FUNCTION((s, p), register char *s AND register char *p)
+{
+ register int scc;
+ int ok, lc;
+ char *sgpathp;
+ struct stat stb;
+ int c, cc;
+
+ globbed = 1;
+ for (;;) {
+ scc = *s++ & TRIM;
+ switch (c = *p++) {
+
+ case '{':
+ return (execbrc(p - 1, s - 1));
+
+ case '[':
+ ok = 0;
+ lc = 077777;
+ while (cc = *p++) {
+ if (cc == ']') {
+ if (ok)
+ break;
+ return (0);
+ }
+ if (cc == '-') {
+ if (lc <= scc && scc <= *p++)
+ ok++;
+ } else
+ if (scc == (lc = cc))
+ ok++;
+ }
+ if (cc == 0)
+ if (ok)
+ p--;
+ else
+ return 0;
+ continue;
+
+ case '*':
+ if (!*p)
+ return (1);
+ if (*p == '/') {
+ p++;
+ goto slash;
+ }
+ s--;
+ do {
+ if (amatch(s, p))
+ return (1);
+ }
+ while (*s++);
+ return (0);
+
+ case 0:
+ return (scc == 0);
+
+ default:
+ if (c != scc)
+ return (0);
+ continue;
+
+ case '?':
+ if (scc == 0)
+ return (0);
+ continue;
+
+ case '/':
+ if (scc)
+ return (0);
+ slash:
+ s = entp;
+ sgpathp = gpathp;
+ while (*s)
+ addpath(*s++);
+ addpath('/');
+ if (stat(gpath, &stb) == 0 && isdir(stb))
+ if (*p == 0) {
+ Gcat(gpath, "");
+ globcnt++;
+ } else
+ expand(p);
+ gpathp = sgpathp;
+ *gpathp = 0;
+ return (0);
+ }
+ }
+}
+
+
+char **ftpglob FUNCTION((v), register char *v)
+{
+ char agpath[BUFSIZ];
+ char *agargv[GAVSIZ];
+ char *vv[2];
+
+ vv[0] = v;
+ vv[1] = 0;
+ gflag = 0;
+ rscan(vv, tglob);
+ if (gflag == 0) {
+ vv[0] = strspl(v, "");
+ return (copyblk(vv));
+ }
+ globerr = 0;
+ gpath = agpath;
+ gpathp = gpath;
+ *gpathp = 0;
+ lastgpathp = &gpath[sizeof agpath - 2];
+ ginit(agargv);
+ globcnt = 0;
+ collect(v);
+ if (globcnt == 0 && (gflag & 1)) {
+ blkfree(gargv), gargv = 0;
+ return (0);
+ } else
+ return (gargv = copyblk(gargv));
+}
diff --git a/contrib/opie/install-sh b/contrib/opie/install-sh
new file mode 100644
index 0000000..89fc9b0
--- /dev/null
+++ b/contrib/opie/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# 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.
+#
+
+
+# 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}"
+
+tranformbasename=""
+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
diff --git a/contrib/opie/libmissing/Makefile.in b/contrib/opie/libmissing/Makefile.in
new file mode 100644
index 0000000..e00ead3
--- /dev/null
+++ b/contrib/opie/libmissing/Makefile.in
@@ -0,0 +1,30 @@
+##
+# Makefile.in/Makefile: Directions for building libmissing.
+#
+# %%% copyright-cmetz
+# This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+# The Inner Net License Version 2 applies to this software.
+# You should have received a copy of the license with this software. If
+# you didn't get a copy, you may request one from <license@inner.net>.
+#
+# History:
+#
+# Created by cmetz for OPIE 2.3 using old Makefiles as a guide.
+
+OBJS=bogus.o @MISSING@
+
+CC=@CC@
+CFLAGS=$(CFL) -I..
+TARGET=libmissing.a
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ ar r $(TARGET) $(OBJS)
+ @RANLIB@ $(TARGET)
+
+clean:
+ -rm -f $(OBJS) $(TARGET)
+
+realclean: clean
+ -rm -f *~ core* "\#*\#" *.o *.a Makefile
diff --git a/contrib/opie/libmissing/alloca.c b/contrib/opie/libmissing/alloca.c
new file mode 100644
index 0000000..61f2eeb
--- /dev/null
+++ b/contrib/opie/libmissing/alloca.c
@@ -0,0 +1,494 @@
+/* alloca.c -- allocate automatically reclaimed memory
+ (Mostly) portable public-domain implementation -- D A Gwyn
+
+ This implementation of the PWB library alloca function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+ J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+ There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed. */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+ there must be some other way alloca is supposed to work. */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+ provide an "address metric" ADDRESS_FUNCTION macro. */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#define NULL 0
+
+/* Different portions of Emacs need to call different versions of
+ malloc. The Emacs executable needs alloca to call xmalloc, because
+ ordinary malloc isn't protected from input signals. On the other
+ hand, the utilities in lib-src need alloca to call malloc; some of
+ them are very simple, and don't have an xmalloc routine.
+
+ Non-Emacs programs expect this to call use xmalloc.
+
+ Callers below should use malloc. */
+
+#if 0
+#ifndef emacs
+#define malloc xmalloc
+#endif
+extern pointer malloc ();
+#endif /* 0 */
+
+/* Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* Direction unknown. */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
+
+#else /* STACK_DIRECTION == 0; need run-time code. */
+
+static int stack_dir; /* 1 or -1 once known. */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction ()
+{
+ static char *addr = NULL; /* Address of first `dummy', once known. */
+ auto char dummy; /* To get stack address. */
+
+ if (addr == NULL)
+ { /* Initial entry. */
+ addr = ADDRESS_FUNCTION (dummy);
+
+ find_stack_direction (); /* Recurse once. */
+ }
+ else
+ {
+ /* Second entry. */
+ if (ADDRESS_FUNCTION (dummy) > addr)
+ stack_dir = 1; /* Stack grew upward. */
+ else
+ stack_dir = -1; /* Stack grew downward. */
+ }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+ (a) chain together all alloca'ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc
+ alignment chunk size. The following default should work okay. */
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* To force sizeof(header). */
+ struct
+ {
+ union hdr *next; /* For chaining headers. */
+ char *deep; /* For stack depth measure. */
+ } h;
+} header;
+
+static header *last_alloca_header = NULL; /* -> last alloca header. */
+
+/* Return a pointer to at least SIZE bytes of storage,
+ which will be automatically reclaimed upon exit from
+ the procedure that called alloca. Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32. */
+
+pointer
+alloca (size)
+ unsigned size;
+{
+ auto char probe; /* Probes stack depth: */
+ register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* Unknown growth direction. */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca'd storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* Traverses linked list. */
+
+#ifdef emacs
+ BLOCK_INPUT;
+#endif
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* Collect garbage. */
+
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ last_alloca_header = hp; /* -> last valid storage. */
+
+#ifdef emacs
+ UNBLOCK_INPUT;
+#endif
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = malloc (sizeof (header) + size);
+ /* Address of header. */
+
+ ((header *) new)->h.next = last_alloca_header;
+ ((header *) new)->h.deep = depth;
+
+ last_alloca_header = (header *) new;
+
+ /* User storage begins just after header. */
+
+ return (pointer) ((char *) new + sizeof (header));
+ }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+ {
+ long shgrow:32; /* Number of times stack has grown. */
+ long shaseg:32; /* Size of increments to stack. */
+ long shhwm:32; /* High water mark of stack. */
+ long shsize:32; /* Current size of stack (all segments). */
+ };
+
+/* The stack segment linkage control information occurs at
+ the high-address end of a stack segment. (The stack
+ grows from low addresses to high addresses.) The initial
+ part of the stack segment linkage control information is
+ 0200 (octal) words. This provides for register storage
+ for the routine which overflows the stack. */
+
+struct stack_segment_linkage
+ {
+ long ss[0200]; /* 0200 overflow words. */
+ long sssize:32; /* Number of words in this segment. */
+ long ssbase:32; /* Offset to stack base. */
+ long:32;
+ long sspseg:32; /* Offset to linkage control of previous
+ segment of stack. */
+ long:32;
+ long sstcpt:32; /* Pointer to task common address block. */
+ long sscsnm; /* Private control structure number for
+ microtasking. */
+ long ssusr1; /* Reserved for user. */
+ long ssusr2; /* Reserved for user. */
+ long sstpid; /* Process ID for pid based multi-tasking. */
+ long ssgvup; /* Pointer to multitasking thread giveup. */
+ long sscray[7]; /* Reserved for Cray Research. */
+ long ssa0;
+ long ssa1;
+ long ssa2;
+ long ssa3;
+ long ssa4;
+ long ssa5;
+ long ssa6;
+ long ssa7;
+ long sss0;
+ long sss1;
+ long sss2;
+ long sss3;
+ long sss4;
+ long sss5;
+ long sss6;
+ long sss7;
+ };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+ returned by the STKSTAT library routine. */
+struct stk_stat
+ {
+ long now; /* Current total stack size. */
+ long maxc; /* Amount of contiguous space which would
+ be required to satisfy the maximum
+ stack demand to date. */
+ long high_water; /* Stack high-water mark. */
+ long overflows; /* Number of stack overflow ($STKOFEN) calls. */
+ long hits; /* Number of internal buffer hits. */
+ long extends; /* Number of block extensions. */
+ long stko_mallocs; /* Block allocations by $STKOFEN. */
+ long underflows; /* Number of stack underflow calls ($STKRETN). */
+ long stko_free; /* Number of deallocations by $STKRETN. */
+ long stkm_free; /* Number of deallocations by $STKMRET. */
+ long segments; /* Current number of stack segments. */
+ long maxs; /* Maximum number of stack segments so far. */
+ long pad_size; /* Stack pad size. */
+ long current_address; /* Current stack segment address. */
+ long current_size; /* Current stack segment size. This
+ number is actually corrupted by STKSTAT to
+ include the fifteen word trailer area. */
+ long initial_address; /* Address of initial segment. */
+ long initial_size; /* Size of initial segment. */
+ };
+
+/* The following structure describes the data structure which trails
+ any stack segment. I think that the description in 'asdef' is
+ out of date. I only describe the parts that I am sure about. */
+
+struct stk_trailer
+ {
+ long this_address; /* Address of this block. */
+ long this_size; /* Size of this block (does not include
+ this trailer). */
+ long unknown2;
+ long unknown3;
+ long link; /* Address of trailer block of previous
+ segment. */
+ long unknown5;
+ long unknown6;
+ long unknown7;
+ long unknown8;
+ long unknown9;
+ long unknown10;
+ long unknown11;
+ long unknown12;
+ long unknown13;
+ long unknown14;
+ };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+ I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+ struct stk_stat status;
+ struct stk_trailer *trailer;
+ long *block, size;
+ long result = 0;
+
+ /* We want to iterate through all of the segments. The first
+ step is to get the stack status structure. We could do this
+ more quickly and more directly, perhaps, by referencing the
+ $LM00 common block, but I know that this works. */
+
+ STKSTAT (&status);
+
+ /* Set up the iteration. */
+
+ trailer = (struct stk_trailer *) (status.current_address
+ + status.current_size
+ - 15);
+
+ /* There must be at least one stack segment. Therefore it is
+ a fatal error if "trailer" is null. */
+
+ if (trailer == 0)
+ abort ();
+
+ /* Discard segments that do not contain our argument address. */
+
+ while (trailer != 0)
+ {
+ block = (long *) trailer->this_address;
+ size = trailer->this_size;
+ if (block == 0 || size == 0)
+ abort ();
+ trailer = (struct stk_trailer *) trailer->link;
+ if ((block <= address) && (address < (block + size)))
+ break;
+ }
+
+ /* Set the result to the offset in this segment and add the sizes
+ of all predecessor segments. */
+
+ result = address - block;
+
+ if (trailer == 0)
+ {
+ return result;
+ }
+
+ do
+ {
+ if (trailer->this_size <= 0)
+ abort ();
+ result += trailer->this_size;
+ trailer = (struct stk_trailer *) trailer->link;
+ }
+ while (trailer != 0);
+
+ /* We are done. Note that if you present a bogus address (one
+ not in any segment), you will get a different number back, formed
+ from subtracting the address of the first block. This is probably
+ not what you want. */
+
+ return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+ Determine the number of the cell within the stack,
+ given the address of the cell. The purpose of this
+ routine is to linearize, in some sense, stack addresses
+ for alloca. */
+
+static long
+i00afunc (long address)
+{
+ long stkl = 0;
+
+ long size, pseg, this_segment, stack;
+ long result = 0;
+
+ struct stack_segment_linkage *ssptr;
+
+ /* Register B67 contains the address of the end of the
+ current stack segment. If you (as a subprogram) store
+ your registers on the stack and find that you are past
+ the contents of B67, you have overflowed the segment.
+
+ B67 also points to the stack segment linkage control
+ area, which is what we are really interested in. */
+
+ stkl = CRAY_STACKSEG_END ();
+ ssptr = (struct stack_segment_linkage *) stkl;
+
+ /* If one subtracts 'size' from the end of the segment,
+ one has the address of the first word of the segment.
+
+ If this is not the first segment, 'pseg' will be
+ nonzero. */
+
+ pseg = ssptr->sspseg;
+ size = ssptr->sssize;
+
+ this_segment = stkl - size;
+
+ /* It is possible that calling this routine itself caused
+ a stack overflow. Discard stack segments which do not
+ contain the target address. */
+
+ while (!(this_segment <= address && address <= stkl))
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+ if (pseg == 0)
+ break;
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ this_segment = stkl - size;
+ }
+
+ result = address - this_segment;
+
+ /* If you subtract pseg from the current end of the stack,
+ you get the address of the previous stack segment's end.
+ This seems a little convoluted to me, but I'll bet you save
+ a cycle somewhere. */
+
+ while (pseg != 0)
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ result += size;
+ }
+ return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
+#endif /* not GCC version 2 */
diff --git a/contrib/opie/libmissing/bogus.c b/contrib/opie/libmissing/bogus.c
new file mode 100644
index 0000000..68dcc54
--- /dev/null
+++ b/contrib/opie/libmissing/bogus.c
@@ -0,0 +1 @@
+int _bogus;
diff --git a/contrib/opie/libmissing/endutent.c b/contrib/opie/libmissing/endutent.c
new file mode 100644
index 0000000..4a4051c
--- /dev/null
+++ b/contrib/opie/libmissing/endutent.c
@@ -0,0 +1,18 @@
+/* endutent.c: A replacement for the endutent function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+void endutent FUNCTION_NOARGS
+{
+}
diff --git a/contrib/opie/libmissing/env.c b/contrib/opie/libmissing/env.c
new file mode 100644
index 0000000..9a445a0
--- /dev/null
+++ b/contrib/opie/libmissing/env.c
@@ -0,0 +1,141 @@
+/* env.c: Replacement environment handling functions.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Changed ifdefs for libmissing.
+ Combined all env functions and made _findenv static.
+ Including headers is a good idea, though. Add more headers.
+ Modified at NRL for OPIE 2.0.
+ Originally from BSD.
+*/
+/*
+ * Copyright (c) 1987 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.
+ */
+
+#include "opie_cfg.h"
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include "opie.h"
+
+static char *_findenv FUNCTION((name, offset), register char *name AND int *offset)
+{
+ extern char **environ;
+ register int len;
+ register char **P, *C;
+
+ for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+ for (P = environ; *P; ++P)
+ if (!strncmp(*P, name, len))
+ if (*(C = *P + len) == '=') {
+ *offset = P - environ;
+ return (++C);
+ }
+ return (NULL);
+}
+
+#if !HAVE_GETENV
+char *getenv FUNCTION((name), char *name)
+{
+ int offset;
+ char *_findenv();
+
+ return (_findenv(name, &offset));
+}
+#endif /* !HAVE_GETENV */
+
+#if !HAVE_SETENV
+int setenv FUNCTION((name, value, rewrite), char *name AND char *value AND int rewrite)
+{
+ extern char **environ;
+ static int alloced; /* if allocated space before */
+ register char *C;
+ int l_value, offset;
+
+ if (*value == '=') /* no `=' in value */
+ ++value;
+ l_value = strlen(value);
+ if ((C = _findenv(name, &offset))) { /* find if already exists */
+ if (!rewrite)
+ return (0);
+ if (strlen(C) >= l_value) { /* old larger; copy over */
+ while (*C++ = *value++);
+ return (0);
+ }
+ } else { /* create new slot */
+ register int cnt;
+ register char **P;
+
+ for (P = environ, cnt = 0; *P; ++P, ++cnt);
+ if (alloced) { /* just increase size */
+ environ = (char **) realloc((char *) environ,
+ (u_int) (sizeof(char *) * (cnt + 2)));
+
+ if (!environ)
+ return (-1);
+ } else { /* get new space */
+ alloced = 1; /* copy old entries into it */
+ P = (char **) malloc((u_int) (sizeof(char *) *
+ (cnt + 2)));
+
+ if (!P)
+ return (-1);
+ strncpy(P, environ, cnt * sizeof(char *));
+
+ environ = P;
+ }
+ environ[cnt + 1] = NULL;
+ offset = cnt;
+ }
+ for (C = name; *C && *C != '='; ++C); /* no `=' in name */
+ if (!(environ[offset] = /* name + `=' + value */
+ malloc((u_int) ((int) (C - name) + l_value + 2))))
+ return (-1);
+ for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
+ for (*C++ = '='; *C++ = *value++;);
+ return (0);
+}
+#endif /* !HAVE_SETENV */
+
+#if !HAVE_UNSETENV
+VOIDRET unsetenv FUNCTION((name), char *name)
+{
+ extern char **environ;
+ register char **P;
+ int offset;
+
+ while (_findenv(name, &offset)) /* if set multiple times */
+ for (P = &environ[offset];; ++P)
+ if (!(*P = *(P + 1)))
+ break;
+}
+#endif /* !HAVE_UNSETENV */
diff --git a/contrib/opie/libmissing/getcwd.c b/contrib/opie/libmissing/getcwd.c
new file mode 100644
index 0000000..30ccdc0
--- /dev/null
+++ b/contrib/opie/libmissing/getcwd.c
@@ -0,0 +1,23 @@
+/* getcwd.c: A replacement for the getcwd function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+char *getcwd FUNCTION((c, l), char *c AND int l)
+{
+#if HAVE_GETWD
+ return getwd(c);
+#else /* HAVE_INDEX */
+#error Need getwd() to build a replacement getcwd()
+#endif /* HAVE_INDEX */
+}
diff --git a/contrib/opie/libmissing/getusershell.c b/contrib/opie/libmissing/getusershell.c
new file mode 100644
index 0000000..885aa04
--- /dev/null
+++ b/contrib/opie/libmissing/getusershell.c
@@ -0,0 +1,67 @@
+/* getusershell.c: minimal implementation of the getusershell() and
+ endusershell() library routines for systems that don't have them.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Modified at NRL for OPIE 2.1. Remove trailing newlines from
+ /etc/shells entries. Fixed infinite loop. Fixed a bug
+ where second invocation on would fail.
+ Written at NRL for OPIE 2.0.
+*/
+#include "opie_cfg.h"
+#include <stdio.h>
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include "opie.h"
+
+static FILE *fh = NULL;
+static char *internal[] = {"/bin/sh", "/bin/csh", NULL};
+static int i = 0;
+static char buffer[1024];
+
+char *getusershell FUNCTION_NOARGS
+{
+ char *c;
+
+ if (!fh)
+ fh = fopen("/etc/shells", "r");
+
+ if (fh) {
+ if (fgets(buffer, sizeof(buffer), fh)) {
+ if (c = strchr(buffer, '\n'))
+ *c = 0;
+ return buffer;
+ } else {
+ fclose(fh);
+ return NULL;
+ }
+ } else {
+ if (internal[i])
+ return internal[i++];
+ else
+ return NULL;
+ }
+}
+
+VOIDRET endusershell FUNCTION_NOARGS
+{
+ if (fh) {
+ fclose(fh);
+ fh = NULL;
+ }
+ i = 0;
+}
diff --git a/contrib/opie/libmissing/getutline.c b/contrib/opie/libmissing/getutline.c
new file mode 100644
index 0000000..9653950
--- /dev/null
+++ b/contrib/opie/libmissing/getutline.c
@@ -0,0 +1,50 @@
+/* getutline.c: A replacement for the getutline() function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+
+#include "opie_cfg.h"
+#include <stdio.h>
+#include <utmp.h>
+#include "opie.h"
+
+static struct utmp u;
+
+struct utmp *getutline FUNCTION((utmp), struct utmp *utmp)
+{
+ FILE *f;
+ int i;
+
+ if (!(f = __opieopen(_PATH_UTMP, 0, 0644)))
+ return 0;
+
+#if HAVE_TTYSLOT
+ if (i = ttyslot()) {
+ if (fseek(f, i * sizeof(struct utmp), SEEK_SET) < 0)
+ goto ret;
+ if (fread(&u, sizeof(struct utmp), 1, f) != sizeof(struct utmp))
+ goto ret;
+ fclose(f);
+ return &u;
+ }
+#endif /* HAVE_TTYSLOT */
+
+ while(fread(&u, sizeof(struct utmp), 1, f) == sizeof(struct utmp)) {
+ if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) - 1)) {
+ fclose(f);
+ return &u;
+ }
+ }
+
+ret:
+ fclose(f);
+ return NULL;
+}
diff --git a/contrib/opie/libmissing/initgroups.c b/contrib/opie/libmissing/initgroups.c
new file mode 100644
index 0000000..2306a0c
--- /dev/null
+++ b/contrib/opie/libmissing/initgroups.c
@@ -0,0 +1,129 @@
+/* initgroups.c: Replacement for the initgroups() function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Removed useless string.
+ Ifdef around headers. Use FUNCTION declarations.
+ Not everyone has multiple groups. Work around
+ lack of NGROUPS.
+ Originally from 4.3BSD Net/2.
+*/
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * initgroups
+ */
+#include "opie_cfg.h"
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#include <stdio.h>
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <grp.h>
+
+#include "opie.h"
+
+struct group *getgrent();
+
+int initgroups FUNCTION((uname, agroup), const char *uname AND int agroup)
+{
+#if HAVE_SETGROUPS && HAVE_GETGROUPS
+#if NGROUPS
+ int groups[NGROUPS];
+#else /* NGROUPS */
+#define STARTING_NGROUPS 32
+ int groups[STARTING_NGROUPS];
+#endif /* NGROUPS */
+ int ngroups;
+ register struct group *grp;
+ register int i;
+
+ /*
+ * If installing primary group, duplicate it;
+ * the first element of groups is the effective gid
+ * and will be overwritten when a setgid file is executed.
+ */
+ if (agroup >= 0) {
+ groups[ngroups++] = agroup;
+ groups[ngroups++] = agroup;
+ }
+ setgrent();
+ while (grp = getgrent()) {
+ if (grp->gr_gid == agroup)
+ continue;
+ for (i = 0; grp->gr_mem[i]; i++)
+ if (!strcmp(grp->gr_mem[i], uname)) {
+#if NGROUPS
+ if (ngroups == NGROUPS) {
+#else /* NGROUPS */
+ if (ngroups == STARTING_NGROUPS) {
+#endif /* NGROUPS */
+fprintf(stderr, "initgroups: %s is in too many groups\n", uname);
+ goto toomany;
+ }
+ groups[ngroups++] = grp->gr_gid;
+ }
+ }
+toomany:
+ endgrent();
+#if NGROUPS
+ if (setgroups(ngroups, groups) < 0) {
+ perror("setgroups");
+ return (-1);
+ }
+#else /* NGROUPS */
+ ngroups++;
+ do {
+ if ((i = setgroups(--ngroups, groups) < 0) && (i != EINVAL)) {
+ perror("setgroups");
+ return (-1);
+ }
+ } while ((i < 0) && (ngroups > 0));
+#endif /* NGROUPS */
+#endif /* HAVE_SETGROUPS && HAVE_GETGROUPS */
+ return (0);
+}
diff --git a/contrib/opie/libmissing/memcmp.c b/contrib/opie/libmissing/memcmp.c
new file mode 100644
index 0000000..e19beaf
--- /dev/null
+++ b/contrib/opie/libmissing/memcmp.c
@@ -0,0 +1,25 @@
+/* strncasecmp.c: A replacement for the strncasecmp function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+int memcmp FUNCTION((s1, s2, n), unsigned char *s1 AND unsigned char *s2 AND int n)
+{
+ while(n--) {
+ if (*s1 != *s2)
+ return (*s1 > *s2) ? 1 : -1;
+ s1++;
+ s2++;
+ }
+ return 0;
+}
diff --git a/contrib/opie/libmissing/memcpy.c b/contrib/opie/libmissing/memcpy.c
new file mode 100644
index 0000000..6d386c2
--- /dev/null
+++ b/contrib/opie/libmissing/memcpy.c
@@ -0,0 +1,25 @@
+/* memcpy.c: A replacement for the memcpy function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+VOIDPTR *memcpy FUNCTION((d, s, n), unsigned char *d AND unsigned char *s AND int n)
+{
+#if HAVE_BCOPY
+ bcopy(s, d, n);
+#else /* HAVE_BCOPY */
+ char *d2 = d;
+ while(n--) (*d2++) = (*s++);
+#endif /* HAVE_BCOPY */
+ return d;
+}
diff --git a/contrib/opie/libmissing/memset.c b/contrib/opie/libmissing/memset.c
new file mode 100644
index 0000000..678c441
--- /dev/null
+++ b/contrib/opie/libmissing/memset.c
@@ -0,0 +1,21 @@
+/* memcpy.c: A replacement for the memcpy function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+VOIDPTR *memset FUNCTION((d, v, n), unsigned char *d AND int v AND int n)
+{
+ unsigned char *d2 = d;
+ while(n--) (*d2++) = (unsigned char)v;
+ return d;
+}
diff --git a/contrib/opie/libmissing/pututline.c b/contrib/opie/libmissing/pututline.c
new file mode 100644
index 0000000..62da458
--- /dev/null
+++ b/contrib/opie/libmissing/pututline.c
@@ -0,0 +1,56 @@
+/* pututline.c: A replacement for the pututline() function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+
+#include "opie_cfg.h"
+#include <stdio.h>
+#include <utmp.h>
+#include "opie.h"
+
+void pututline FUNCTION((utmp), struct utmp *utmp)
+{
+ FILE *f;
+ struct utmp u;
+ int i;
+
+ if (!(f = __opieopen(_PATH_UTMP, 1, 0644)))
+ return;
+
+#if HAVE_TTYSLOT
+ if (i = ttyslot()) {
+ if (fseek(f, i * sizeof(struct utmp), SEEK_SET) < 0)
+ goto ret;
+ fwrite(utmp, sizeof(struct utmp), 1, f);
+ goto ret;
+ }
+#endif /* HAVE_TTYSLOT */
+
+ while(fread(&u, sizeof(struct utmp), 1, f) == sizeof(struct utmp)) {
+ if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) - 1)) {
+ if ((i = ftell(f)) < 0)
+ goto ret;
+ if (fseek(f, i - sizeof(struct utmp), SEEK_SET) < 0)
+ goto ret;
+ fwrite(utmp, sizeof(struct utmp), 1, f);
+ goto ret;
+ }
+ }
+
+ fclose(f);
+
+ if (!(f = __opieopen(_PATH_UTMP, 2, 0644)))
+ return;
+ fwrite(utmp, sizeof(struct utmp), 1, f);
+
+ret:
+ fclose(f);
+}
diff --git a/contrib/opie/libmissing/sigaddset.c b/contrib/opie/libmissing/sigaddset.c
new file mode 100644
index 0000000..56a613b
--- /dev/null
+++ b/contrib/opie/libmissing/sigaddset.c
@@ -0,0 +1,36 @@
+/* sigaddset.c: A replacement for the sigaddset function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.2.
+*/
+
+#include "opie_cfg.h"
+
+#ifndef _NSIG
+#ifdef NSIG
+#define _NSIG NSIG
+#else /* NSIG */
+#define _NSIG 32
+#endif /* NSIG */
+#endif /* _NSIG */
+
+#include "opie.h"
+
+int sigaddset FUNCTION((set, signum), sigset_t *set AND int signum)
+{
+#if sizeof(sigset_t) != sizeof(int)
+Sorry, we don't currently support your system.
+#else /* sizeof(sigset_t) != sizeof(int) */
+ if (set && (signum > 0) && (signum < _NSIG))
+ *set |= 1 << (signum - 1);
+#endif /* sizeof(sigset_t) != sizeof(int) */
+
+ return 0;
+}
diff --git a/contrib/opie/libmissing/sigemptyset.c b/contrib/opie/libmissing/sigemptyset.c
new file mode 100644
index 0000000..fc083f5
--- /dev/null
+++ b/contrib/opie/libmissing/sigemptyset.c
@@ -0,0 +1,23 @@
+/* sigemptyset.c: A replacement for the sigemptyset function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.2.
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+int sigemptyset FUNCTION((set), sigset_t *set)
+{
+ if (set)
+ memset(set, 0, sizeof(sigset_t))
+
+ return 0;
+}
diff --git a/contrib/opie/libmissing/sigprocmask.c b/contrib/opie/libmissing/sigprocmask.c
new file mode 100644
index 0000000..4af1559
--- /dev/null
+++ b/contrib/opie/libmissing/sigprocmask.c
@@ -0,0 +1,68 @@
+/* sigprocmask.c: A replacement for the sigprocmask() function
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Created by cmetz for OPIE 2.2 from popen.c. Use FUNCTION
+ declaration et al. Include opie.h.
+*/
+
+#include "opie_cfg.h"
+
+#include <sys/types.h>
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+#if HAVE_SYS_SIGNAL_H
+#include <sys/signal.h>
+#endif /* HAVE_SYS_SIGNAL_H */
+
+#if !HAVE_SIGBLOCK || !HAVE_SIGSETMASK
+Without sigblock and sigsetmask, we can't build a replacement sigprocmask.
+#endif /* !HAVE_SIGBLOCK || !HAVE_SIGSETMASK */
+
+#include "opie.h"
+
+#ifndef sigset_t
+#define sigset_t int
+#endif /* sigset_t */
+
+int sigprocmask FUNCTION((how, set, oset), int how AND sigset_t *set AND sigset_t *oset)
+{
+ int old, new;
+
+ if (set && (set != (sigset_t *)SIG_IGN) && (set != (sigset_t *)SIG_ERR))
+ new = *set;
+ else
+ new = 0;
+
+ switch(how) {
+ case SIG_BLOCK:
+ old = sigblock(new);
+ if (oset && (oset != (sigset_t *)SIG_IGN) && (oset != (sigset_t *)SIG_ERR))
+ *oset = old;
+ return 0;
+
+ case SIG_SETMASK:
+ old = sigsetmask(new);
+ if (oset && (oset != (sigset_t *)SIG_IGN) && (oset != (sigset_t *)SIG_ERR))
+ *oset = old;
+ return 0;
+
+ case SIG_UNBLOCK:
+ /* not implemented */
+ default:
+ return 0;
+ }
+}
diff --git a/contrib/opie/libmissing/strchr.c b/contrib/opie/libmissing/strchr.c
new file mode 100644
index 0000000..2903bc4
--- /dev/null
+++ b/contrib/opie/libmissing/strchr.c
@@ -0,0 +1,24 @@
+/* strchr.c: A replacement for the strchr function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+char *strchr FUNCTION((s, c), char *s AND int c)
+{
+#if HAVE_INDEX
+ return index(s, c);
+#else /* HAVE_INDEX */
+ while(*s && (*s != c)) s++;
+ return *s ? s : (char *)0;
+#endif /* HAVE_INDEX */
+}
diff --git a/contrib/opie/libmissing/strerror.c b/contrib/opie/libmissing/strerror.c
new file mode 100644
index 0000000..89632f9
--- /dev/null
+++ b/contrib/opie/libmissing/strerror.c
@@ -0,0 +1,34 @@
+/* strerror.c: A replacement for the strerror function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.2.
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+char *strerror FUNCTION((errnum), int errnum)
+{
+#if HAVE_SYS_ERRLIST
+ extern char *sys_errlist[];
+ return sys_errlist[errnum];
+#else /* NEED_STRERROR */
+#if HAVE__SYS_ERRLIST
+ extern char *_sys_errlist[];
+ return sys_errlist[errnum];
+#else /* HAVE__SYS_ERRLIST */
+ static char hexdigits[] = "0123456789abcdef";
+ static char buffer[] = "System error 0x42";
+ buffer[15] = hexdigits[(errnum >> 4) & 0x0f];
+ buffer[16] = hexdigits[errnum & 0x0f];
+ return buffer;
+#endif /* HAVE__SYS_ERRLIST */
+#endif /* NEED_STRERROR */
+}
diff --git a/contrib/opie/libmissing/strncasecmp.c b/contrib/opie/libmissing/strncasecmp.c
new file mode 100644
index 0000000..e90b4c0
--- /dev/null
+++ b/contrib/opie/libmissing/strncasecmp.c
@@ -0,0 +1,30 @@
+/* strncasecmp.c: A replacement for the strncasecmp function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+int strncasecmp FUNCTION((s1, s2, n), unsigned char *s1 AND unsigned char *s2 AND int n)
+{
+ unsigned char c1, c2;
+ while(*s1 && *s2 && n--) {
+ c1 = ((*s1 >= 'A') && (*s1 <= 'Z')) ? (*s1++) + ('a' - 'A') : (*s1++);
+ c2 = ((*s2 >= 'A') && (*s2 <= 'Z')) ? (*s2++) + ('a' - 'A') : (*s2++);
+ if (c1 != c2)
+ return (c1 > c2) ? 1 : -1;
+ }
+ if (*s1 && !*s2)
+ return 1;
+ if (!*s1 && *s2)
+ return -1;
+ return 0;
+}
diff --git a/contrib/opie/libmissing/strrchr.c b/contrib/opie/libmissing/strrchr.c
new file mode 100644
index 0000000..04d46ce
--- /dev/null
+++ b/contrib/opie/libmissing/strrchr.c
@@ -0,0 +1,25 @@
+/* strrchr.c: A replacement for the strrchr function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+char *strrchr FUNCTION((s, c), char *s AND int c)
+{
+#if HAVE_RINDEX
+ return rindex(s, c);
+#else /* HAVE_RINDEX */
+ char *s2 = (char *)0;
+ while(*s) { if (*s == c) s2 = s; s++ };
+ return s2;
+#endif /* HAVE_RINDEX */
+}
diff --git a/contrib/opie/libmissing/sysconf.c b/contrib/opie/libmissing/sysconf.c
new file mode 100644
index 0000000..fb3a5bc
--- /dev/null
+++ b/contrib/opie/libmissing/sysconf.c
@@ -0,0 +1,30 @@
+/* sysconf.c: A (partial) replacement for the sysconf function
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+#include "opie_cfg.h"
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#include "opie.h"
+
+long sysconf(int name)
+{
+ switch(name) {
+ case _SC_OPEN_MAX:
+#if HAVE_GETDTABLESIZE
+ return getdtablesize();
+#else /* HAVE_GETDTABLESIZE */
+#error Need getdtablesize() to build a replacement sysconf()
+#endif /* HAVE_GETDTABLESIZE */
+
+ return -1;
+}
diff --git a/contrib/opie/libmissing/uname.c b/contrib/opie/libmissing/uname.c
new file mode 100644
index 0000000..5b51fa5
--- /dev/null
+++ b/contrib/opie/libmissing/uname.c
@@ -0,0 +1,42 @@
+/* uname.c: A replacement for the uname function (sort of)
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Ifdef around gethostname().
+ Created by cmetz for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#include "opie.h"
+
+int uname FUNCTION(struct utsname *buf)
+{
+#if HAVE_GETHOSTNAME
+ char hostname[MAXHOSTNAMELEN], *c;
+
+ memset(buf, 0, sizeof(buf));
+
+ if (gethostname(hostname, sizeof(hostname)-1) < 0)
+ return -1;
+
+ hostname[sizeof(hostname) - 1] = 0;
+
+ if (c = strchr(hostname, '.')) {
+ *c = 0;
+ }
+
+ strncpy(buf->nodename, hostname, sizeof(buf->nodename) - 1);
+ return 0;
+#else /* HAVE_GETHOSTNAME */
+ strncpy(buf->nodename, "unknown", sizeof(buf->nodename) - 1);
+ return 0;
+#endif /* HAVE_GETHOSTNAME */
+}
diff --git a/contrib/opie/libopie/Makefile.in b/contrib/opie/libopie/Makefile.in
new file mode 100644
index 0000000..99ab4e7
--- /dev/null
+++ b/contrib/opie/libopie/Makefile.in
@@ -0,0 +1,28 @@
+##
+# Makefile.in/Makefile: Directions for building libopie.
+#
+# This software is Copyright 1996 by Craig Metz, All Rights Reserved. The Inner
+# Net Copyright Notice and License Agreement version 2.00 applies to this
+# software.
+#
+# History:
+#
+# Created by cmetz for OPIE 2.3 using old Makefiles as a guide.
+
+OBJS=md4c.o md5c.o atob8.o btoa8.o btoh.o challenge.o getsequence.o hash.o hashlen.o keycrunch.o lock.o lookup.o newseed.o parsechallenge.o passcheck.o passwd.o randomchallenge.o readpass.o unlock.o verify.o version.o btoe.o accessfile.o generator.o insecure.o getutmpentry.o readrec.o writerec.o login.o open.o
+
+CC=@CC@
+CFLAGS=$(CFL) -I..
+TARGET=libopie.a
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ ar r $(TARGET) $(OBJS)
+ @RANLIB@ $(TARGET)
+
+clean:
+ -rm -f $(OBJS) $(TARGET)
+
+realclean: clean
+ -rm -f *~ core* "\#*\#" *.o *.a Makefile
diff --git a/contrib/opie/libopie/accessfile.c b/contrib/opie/libopie/accessfile.c
new file mode 100644
index 0000000..7b1866e
--- /dev/null
+++ b/contrib/opie/libopie/accessfile.c
@@ -0,0 +1,165 @@
+/* accessfile.c: Handle trusted network access file and per-user
+ overrides.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Send debug info to syslog.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Ifdef around some headers. Remove extra semicolon.
+ Modified at NRL for OPIE 2.2. Moved from accessfile.c to
+ libopie/opieaccessfile.c.
+ Modified at NRL for OPIE 2.0.
+ Written at Bellcore for the S/Key Version 1 software distribution
+ (login.c).
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#include "opie.h"
+
+int opieaccessfile FUNCTION((host), char *host)
+{
+#ifdef PATH_ACCESS_FILE
+/* Turn host into an IP address and then look it up in the authorization
+ * database to determine if ordinary password logins are OK
+ */
+ long n;
+ struct hostent *hp;
+ FILE *fp;
+ char buf[128], **lp;
+
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "accessfile: host=%s", host);
+#endif /* DEBUG */
+ if (!host[0])
+ /* Local login, okay */
+ return (1);
+ if (isaddr(host)) {
+ n = inet_addr(host);
+ return rdnets(n);
+ } else {
+ hp = gethostbyname(host);
+ if (!hp) {
+ printf("Unknown host %s\n", host);
+ return 0;
+ }
+ for (lp = hp->h_addr_list; *lp; lp++) {
+ memcpy((char *) &n, *lp, sizeof(n));
+ if (rdnets(n))
+ return (1);
+ }
+ return (0);
+ }
+}
+
+int rdnets FUNCTION((host), long host)
+{
+ FILE *fp;
+ char buf[128], *cp;
+ long pattern, mask;
+ int permit_it;
+
+ if (!(fp = fopen(PATH_ACCESS_FILE, "r")))
+ return 0;
+
+ while (fgets(buf, sizeof(buf), fp), !feof(fp)) {
+ if (buf[0] == '#')
+ continue; /* Comment */
+ if (!(cp = strtok(buf, " \t")))
+ continue;
+ /* two choices permit of deny */
+ if (strncasecmp(cp, "permit", 4) == 0) {
+ permit_it = 1;
+ } else {
+ if (strncasecmp(cp, "deny", 4) == 0) {
+ permit_it = 0;
+ } else {
+ continue; /* ignore; it is not permit/deny */
+ }
+ }
+ if (!(cp = strtok(NULL, " \t")))
+ continue; /* Invalid line */
+ pattern = inet_addr(cp);
+ if (!(cp = strtok(NULL, " \t")))
+ continue; /* Invalid line */
+ mask = inet_addr(cp);
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "accessfile: %08x & %08x == %08x (%s)", host, mask, pattern, ((host & mask) == pattern) ? "true" : "false");
+#endif /* DEBUG */
+ if ((host & mask) == pattern) {
+ fclose(fp);
+ return permit_it;
+ }
+ }
+ fclose(fp);
+ return 0;
+}
+
+
+/* Return TRUE if string appears to be an IP address in dotted decimal;
+ * return FALSE otherwise (i.e., if string is a domain name)
+ */
+int isaddr FUNCTION((s), register char *s)
+{
+ char c;
+
+ if (!s)
+ return 1; /* Can't happen */
+
+ while ((c = *s++) != '\0') {
+ if (c != '[' && c != ']' && !isdigit(c) && c != '.')
+ return 0;
+ }
+ return 1;
+#else /* PATH_ACCESS_FILE */
+ return !host[0];
+#endif /* PATH_ACCESS_FILE */
+}
+
+/* Returns the opposite of what you might expect */
+/* Returns 1 on error (allow)... this might not be what you want */
+int opiealways FUNCTION((homedir), char *homedir)
+{
+ char *opiealwayspath;
+ int i;
+
+ if (!homedir)
+ return 1;
+
+ if (!(opiealwayspath = malloc(strlen(homedir) + sizeof(OPIE_ALWAYS_FILE) + 1)))
+ return 1;
+
+ strcpy(opiealwayspath, homedir);
+ strcat(opiealwayspath, "/");
+ strcat(opiealwayspath, OPIE_ALWAYS_FILE);
+ i = access(opiealwayspath, F_OK);
+ free(opiealwayspath);
+ return (i);
+}
diff --git a/contrib/opie/libopie/atob8.c b/contrib/opie/libopie/atob8.c
new file mode 100644
index 0000000..2c23478
--- /dev/null
+++ b/contrib/opie/libopie/atob8.c
@@ -0,0 +1,74 @@
+/* atob8.c: The opieatob8() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Return the output variable.
+ Don't check parameters.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Inlined and obseleted opieskipspace(). Inlined and obseleted
+ opiehtoi().
+ Created at NRL for OPIE 2.2 from opiesubr2.c
+*/
+#include "opie_cfg.h"
+#include <stdio.h>
+#include "opie.h"
+
+/* Convert 8-byte hex-ascii string to binary array
+ */
+char *opieatob8 FUNCTION((out, in), char *out AND char *in)
+{
+ register int i;
+ register int val;
+
+ for (i = 0; i < 8; i++) {
+ while (*in == ' ' || *in == '\t')
+ in++;
+ if (!*in)
+ return NULL;
+
+ if ((*in >= '0') && (*in <= '9'))
+ val = *(in++) - '0';
+ else
+ if ((*in >= 'a') && (*in <= 'f'))
+ val = *(in++) - 'a' + 10;
+ else
+ if ((*in >= 'A') && (*in <= 'F'))
+ val = *(in++) - 'A' + 10;
+ else
+ return NULL;
+
+ *out = val << 4;
+
+ while (*in == ' ' || *in == '\t')
+ in++;
+ if (!*in)
+ return NULL;
+
+ if ((*in >= '0') && (*in <= '9'))
+ val = *(in++) - '0';
+ else
+ if ((*in >= 'a') && (*in <= 'f'))
+ val = *(in++) - 'a' + 10;
+ else
+ if ((*in >= 'A') && (*in <= 'F'))
+ val = *(in++) - 'A' + 10;
+ else
+ return NULL;
+
+ *out++ |= val;
+ }
+
+ return out;
+}
diff --git a/contrib/opie/libopie/btoa8.c b/contrib/opie/libopie/btoa8.c
new file mode 100644
index 0000000..8696a74
--- /dev/null
+++ b/contrib/opie/libopie/btoa8.c
@@ -0,0 +1,32 @@
+/* btoa8.c: The opiebtoa8() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 (quick re-write).
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+static char hextochar[16] =
+{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+char *opiebtoa8 FUNCTION((out, in), char *out AND char *in)
+{
+ int i;
+ char *c = out;
+
+ for (i = 0; i < 8; i++) {
+ *(c++) = hextochar[((*in) >> 4) & 0x0f];
+ *(c++) = hextochar[(*in++) & 0x0f];
+ }
+ *c = 0;
+
+ return out;
+}
diff --git a/contrib/opie/libopie/btoe.c b/contrib/opie/libopie/btoe.c
new file mode 100644
index 0000000..e402e69
--- /dev/null
+++ b/contrib/opie/libopie/btoe.c
@@ -0,0 +1,2266 @@
+/* btoe: The opiebtoe() and opieetob() library functions:
+ Conversion to/from the six-English-word representation of a
+ 64 bit OTP.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Remove unnecessary address futzing with Wp in opiebtoe.
+ Changed unsigned long to UINT4 for Alpha.
+ Modified at NRL for OPIE 2.2. Moved from put.c to libopie/opiebtoe.c.
+ Modified at NRL for OPIE 2.0.
+ Written at Bellcore for the S/Key Version 1 software distribution.
+*/
+#include "opie_cfg.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "opie.h"
+
+static UINT4 extract __P((char *s, int start, int length));
+static VOIDRET insert __P((char *s, int x, int start, int length));
+static int wsrch __P((char *w, int low, int high));
+
+/* Dictionary for integer-word translations */
+static char Wp[2048][4] =
+{
+ "A",
+ "ABE",
+ "ACE",
+ "ACT",
+ "AD",
+ "ADA",
+ "ADD",
+ "AGO",
+ "AID",
+ "AIM",
+ "AIR",
+ "ALL",
+ "ALP",
+ "AM",
+ "AMY",
+ "AN",
+ "ANA",
+ "AND",
+ "ANN",
+ "ANT",
+ "ANY",
+ "APE",
+ "APS",
+ "APT",
+ "ARC",
+ "ARE",
+ "ARK",
+ "ARM",
+ "ART",
+ "AS",
+ "ASH",
+ "ASK",
+ "AT",
+ "ATE",
+ "AUG",
+ "AUK",
+ "AVE",
+ "AWE",
+ "AWK",
+ "AWL",
+ "AWN",
+ "AX",
+ "AYE",
+ "BAD",
+ "BAG",
+ "BAH",
+ "BAM",
+ "BAN",
+ "BAR",
+ "BAT",
+ "BAY",
+ "BE",
+ "BED",
+ "BEE",
+ "BEG",
+ "BEN",
+ "BET",
+ "BEY",
+ "BIB",
+ "BID",
+ "BIG",
+ "BIN",
+ "BIT",
+ "BOB",
+ "BOG",
+ "BON",
+ "BOO",
+ "BOP",
+ "BOW",
+ "BOY",
+ "BUB",
+ "BUD",
+ "BUG",
+ "BUM",
+ "BUN",
+ "BUS",
+ "BUT",
+ "BUY",
+ "BY",
+ "BYE",
+ "CAB",
+ "CAL",
+ "CAM",
+ "CAN",
+ "CAP",
+ "CAR",
+ "CAT",
+ "CAW",
+ "COD",
+ "COG",
+ "COL",
+ "CON",
+ "COO",
+ "COP",
+ "COT",
+ "COW",
+ "COY",
+ "CRY",
+ "CUB",
+ "CUE",
+ "CUP",
+ "CUR",
+ "CUT",
+ "DAB",
+ "DAD",
+ "DAM",
+ "DAN",
+ "DAR",
+ "DAY",
+ "DEE",
+ "DEL",
+ "DEN",
+ "DES",
+ "DEW",
+ "DID",
+ "DIE",
+ "DIG",
+ "DIN",
+ "DIP",
+ "DO",
+ "DOE",
+ "DOG",
+ "DON",
+ "DOT",
+ "DOW",
+ "DRY",
+ "DUB",
+ "DUD",
+ "DUE",
+ "DUG",
+ "DUN",
+ "EAR",
+ "EAT",
+ "ED",
+ "EEL",
+ "EGG",
+ "EGO",
+ "ELI",
+ "ELK",
+ "ELM",
+ "ELY",
+ "EM",
+ "END",
+ "EST",
+ "ETC",
+ "EVA",
+ "EVE",
+ "EWE",
+ "EYE",
+ "FAD",
+ "FAN",
+ "FAR",
+ "FAT",
+ "FAY",
+ "FED",
+ "FEE",
+ "FEW",
+ "FIB",
+ "FIG",
+ "FIN",
+ "FIR",
+ "FIT",
+ "FLO",
+ "FLY",
+ "FOE",
+ "FOG",
+ "FOR",
+ "FRY",
+ "FUM",
+ "FUN",
+ "FUR",
+ "GAB",
+ "GAD",
+ "GAG",
+ "GAL",
+ "GAM",
+ "GAP",
+ "GAS",
+ "GAY",
+ "GEE",
+ "GEL",
+ "GEM",
+ "GET",
+ "GIG",
+ "GIL",
+ "GIN",
+ "GO",
+ "GOT",
+ "GUM",
+ "GUN",
+ "GUS",
+ "GUT",
+ "GUY",
+ "GYM",
+ "GYP",
+ "HA",
+ "HAD",
+ "HAL",
+ "HAM",
+ "HAN",
+ "HAP",
+ "HAS",
+ "HAT",
+ "HAW",
+ "HAY",
+ "HE",
+ "HEM",
+ "HEN",
+ "HER",
+ "HEW",
+ "HEY",
+ "HI",
+ "HID",
+ "HIM",
+ "HIP",
+ "HIS",
+ "HIT",
+ "HO",
+ "HOB",
+ "HOC",
+ "HOE",
+ "HOG",
+ "HOP",
+ "HOT",
+ "HOW",
+ "HUB",
+ "HUE",
+ "HUG",
+ "HUH",
+ "HUM",
+ "HUT",
+ "I",
+ "ICY",
+ "IDA",
+ "IF",
+ "IKE",
+ "ILL",
+ "INK",
+ "INN",
+ "IO",
+ "ION",
+ "IQ",
+ "IRA",
+ "IRE",
+ "IRK",
+ "IS",
+ "IT",
+ "ITS",
+ "IVY",
+ "JAB",
+ "JAG",
+ "JAM",
+ "JAN",
+ "JAR",
+ "JAW",
+ "JAY",
+ "JET",
+ "JIG",
+ "JIM",
+ "JO",
+ "JOB",
+ "JOE",
+ "JOG",
+ "JOT",
+ "JOY",
+ "JUG",
+ "JUT",
+ "KAY",
+ "KEG",
+ "KEN",
+ "KEY",
+ "KID",
+ "KIM",
+ "KIN",
+ "KIT",
+ "LA",
+ "LAB",
+ "LAC",
+ "LAD",
+ "LAG",
+ "LAM",
+ "LAP",
+ "LAW",
+ "LAY",
+ "LEA",
+ "LED",
+ "LEE",
+ "LEG",
+ "LEN",
+ "LEO",
+ "LET",
+ "LEW",
+ "LID",
+ "LIE",
+ "LIN",
+ "LIP",
+ "LIT",
+ "LO",
+ "LOB",
+ "LOG",
+ "LOP",
+ "LOS",
+ "LOT",
+ "LOU",
+ "LOW",
+ "LOY",
+ "LUG",
+ "LYE",
+ "MA",
+ "MAC",
+ "MAD",
+ "MAE",
+ "MAN",
+ "MAO",
+ "MAP",
+ "MAT",
+ "MAW",
+ "MAY",
+ "ME",
+ "MEG",
+ "MEL",
+ "MEN",
+ "MET",
+ "MEW",
+ "MID",
+ "MIN",
+ "MIT",
+ "MOB",
+ "MOD",
+ "MOE",
+ "MOO",
+ "MOP",
+ "MOS",
+ "MOT",
+ "MOW",
+ "MUD",
+ "MUG",
+ "MUM",
+ "MY",
+ "NAB",
+ "NAG",
+ "NAN",
+ "NAP",
+ "NAT",
+ "NAY",
+ "NE",
+ "NED",
+ "NEE",
+ "NET",
+ "NEW",
+ "NIB",
+ "NIL",
+ "NIP",
+ "NIT",
+ "NO",
+ "NOB",
+ "NOD",
+ "NON",
+ "NOR",
+ "NOT",
+ "NOV",
+ "NOW",
+ "NU",
+ "NUN",
+ "NUT",
+ "O",
+ "OAF",
+ "OAK",
+ "OAR",
+ "OAT",
+ "ODD",
+ "ODE",
+ "OF",
+ "OFF",
+ "OFT",
+ "OH",
+ "OIL",
+ "OK",
+ "OLD",
+ "ON",
+ "ONE",
+ "OR",
+ "ORB",
+ "ORE",
+ "ORR",
+ "OS",
+ "OTT",
+ "OUR",
+ "OUT",
+ "OVA",
+ "OW",
+ "OWE",
+ "OWL",
+ "OWN",
+ "OX",
+ "PA",
+ "PAD",
+ "PAL",
+ "PAM",
+ "PAN",
+ "PAP",
+ "PAR",
+ "PAT",
+ "PAW",
+ "PAY",
+ "PEA",
+ "PEG",
+ "PEN",
+ "PEP",
+ "PER",
+ "PET",
+ "PEW",
+ "PHI",
+ "PI",
+ "PIE",
+ "PIN",
+ "PIT",
+ "PLY",
+ "PO",
+ "POD",
+ "POE",
+ "POP",
+ "POT",
+ "POW",
+ "PRO",
+ "PRY",
+ "PUB",
+ "PUG",
+ "PUN",
+ "PUP",
+ "PUT",
+ "QUO",
+ "RAG",
+ "RAM",
+ "RAN",
+ "RAP",
+ "RAT",
+ "RAW",
+ "RAY",
+ "REB",
+ "RED",
+ "REP",
+ "RET",
+ "RIB",
+ "RID",
+ "RIG",
+ "RIM",
+ "RIO",
+ "RIP",
+ "ROB",
+ "ROD",
+ "ROE",
+ "RON",
+ "ROT",
+ "ROW",
+ "ROY",
+ "RUB",
+ "RUE",
+ "RUG",
+ "RUM",
+ "RUN",
+ "RYE",
+ "SAC",
+ "SAD",
+ "SAG",
+ "SAL",
+ "SAM",
+ "SAN",
+ "SAP",
+ "SAT",
+ "SAW",
+ "SAY",
+ "SEA",
+ "SEC",
+ "SEE",
+ "SEN",
+ "SET",
+ "SEW",
+ "SHE",
+ "SHY",
+ "SIN",
+ "SIP",
+ "SIR",
+ "SIS",
+ "SIT",
+ "SKI",
+ "SKY",
+ "SLY",
+ "SO",
+ "SOB",
+ "SOD",
+ "SON",
+ "SOP",
+ "SOW",
+ "SOY",
+ "SPA",
+ "SPY",
+ "SUB",
+ "SUD",
+ "SUE",
+ "SUM",
+ "SUN",
+ "SUP",
+ "TAB",
+ "TAD",
+ "TAG",
+ "TAN",
+ "TAP",
+ "TAR",
+ "TEA",
+ "TED",
+ "TEE",
+ "TEN",
+ "THE",
+ "THY",
+ "TIC",
+ "TIE",
+ "TIM",
+ "TIN",
+ "TIP",
+ "TO",
+ "TOE",
+ "TOG",
+ "TOM",
+ "TON",
+ "TOO",
+ "TOP",
+ "TOW",
+ "TOY",
+ "TRY",
+ "TUB",
+ "TUG",
+ "TUM",
+ "TUN",
+ "TWO",
+ "UN",
+ "UP",
+ "US",
+ "USE",
+ "VAN",
+ "VAT",
+ "VET",
+ "VIE",
+ "WAD",
+ "WAG",
+ "WAR",
+ "WAS",
+ "WAY",
+ "WE",
+ "WEB",
+ "WED",
+ "WEE",
+ "WET",
+ "WHO",
+ "WHY",
+ "WIN",
+ "WIT",
+ "WOK",
+ "WON",
+ "WOO",
+ "WOW",
+ "WRY",
+ "WU",
+ "YAM",
+ "YAP",
+ "YAW",
+ "YE",
+ "YEA",
+ "YES",
+ "YET",
+ "YOU",
+ "ABED",
+ "ABEL",
+ "ABET",
+ "ABLE",
+ "ABUT",
+ "ACHE",
+ "ACID",
+ "ACME",
+ "ACRE",
+ "ACTA",
+ "ACTS",
+ "ADAM",
+ "ADDS",
+ "ADEN",
+ "AFAR",
+ "AFRO",
+ "AGEE",
+ "AHEM",
+ "AHOY",
+ "AIDA",
+ "AIDE",
+ "AIDS",
+ "AIRY",
+ "AJAR",
+ "AKIN",
+ "ALAN",
+ "ALEC",
+ "ALGA",
+ "ALIA",
+ "ALLY",
+ "ALMA",
+ "ALOE",
+ "ALSO",
+ "ALTO",
+ "ALUM",
+ "ALVA",
+ "AMEN",
+ "AMES",
+ "AMID",
+ "AMMO",
+ "AMOK",
+ "AMOS",
+ "AMRA",
+ "ANDY",
+ "ANEW",
+ "ANNA",
+ "ANNE",
+ "ANTE",
+ "ANTI",
+ "AQUA",
+ "ARAB",
+ "ARCH",
+ "AREA",
+ "ARGO",
+ "ARID",
+ "ARMY",
+ "ARTS",
+ "ARTY",
+ "ASIA",
+ "ASKS",
+ "ATOM",
+ "AUNT",
+ "AURA",
+ "AUTO",
+ "AVER",
+ "AVID",
+ "AVIS",
+ "AVON",
+ "AVOW",
+ "AWAY",
+ "AWRY",
+ "BABE",
+ "BABY",
+ "BACH",
+ "BACK",
+ "BADE",
+ "BAIL",
+ "BAIT",
+ "BAKE",
+ "BALD",
+ "BALE",
+ "BALI",
+ "BALK",
+ "BALL",
+ "BALM",
+ "BAND",
+ "BANE",
+ "BANG",
+ "BANK",
+ "BARB",
+ "BARD",
+ "BARE",
+ "BARK",
+ "BARN",
+ "BARR",
+ "BASE",
+ "BASH",
+ "BASK",
+ "BASS",
+ "BATE",
+ "BATH",
+ "BAWD",
+ "BAWL",
+ "BEAD",
+ "BEAK",
+ "BEAM",
+ "BEAN",
+ "BEAR",
+ "BEAT",
+ "BEAU",
+ "BECK",
+ "BEEF",
+ "BEEN",
+ "BEER",
+ "BEET",
+ "BELA",
+ "BELL",
+ "BELT",
+ "BEND",
+ "BENT",
+ "BERG",
+ "BERN",
+ "BERT",
+ "BESS",
+ "BEST",
+ "BETA",
+ "BETH",
+ "BHOY",
+ "BIAS",
+ "BIDE",
+ "BIEN",
+ "BILE",
+ "BILK",
+ "BILL",
+ "BIND",
+ "BING",
+ "BIRD",
+ "BITE",
+ "BITS",
+ "BLAB",
+ "BLAT",
+ "BLED",
+ "BLEW",
+ "BLOB",
+ "BLOC",
+ "BLOT",
+ "BLOW",
+ "BLUE",
+ "BLUM",
+ "BLUR",
+ "BOAR",
+ "BOAT",
+ "BOCA",
+ "BOCK",
+ "BODE",
+ "BODY",
+ "BOGY",
+ "BOHR",
+ "BOIL",
+ "BOLD",
+ "BOLO",
+ "BOLT",
+ "BOMB",
+ "BONA",
+ "BOND",
+ "BONE",
+ "BONG",
+ "BONN",
+ "BONY",
+ "BOOK",
+ "BOOM",
+ "BOON",
+ "BOOT",
+ "BORE",
+ "BORG",
+ "BORN",
+ "BOSE",
+ "BOSS",
+ "BOTH",
+ "BOUT",
+ "BOWL",
+ "BOYD",
+ "BRAD",
+ "BRAE",
+ "BRAG",
+ "BRAN",
+ "BRAY",
+ "BRED",
+ "BREW",
+ "BRIG",
+ "BRIM",
+ "BROW",
+ "BUCK",
+ "BUDD",
+ "BUFF",
+ "BULB",
+ "BULK",
+ "BULL",
+ "BUNK",
+ "BUNT",
+ "BUOY",
+ "BURG",
+ "BURL",
+ "BURN",
+ "BURR",
+ "BURT",
+ "BURY",
+ "BUSH",
+ "BUSS",
+ "BUST",
+ "BUSY",
+ "BYTE",
+ "CADY",
+ "CAFE",
+ "CAGE",
+ "CAIN",
+ "CAKE",
+ "CALF",
+ "CALL",
+ "CALM",
+ "CAME",
+ "CANE",
+ "CANT",
+ "CARD",
+ "CARE",
+ "CARL",
+ "CARR",
+ "CART",
+ "CASE",
+ "CASH",
+ "CASK",
+ "CAST",
+ "CAVE",
+ "CEIL",
+ "CELL",
+ "CENT",
+ "CERN",
+ "CHAD",
+ "CHAR",
+ "CHAT",
+ "CHAW",
+ "CHEF",
+ "CHEN",
+ "CHEW",
+ "CHIC",
+ "CHIN",
+ "CHOU",
+ "CHOW",
+ "CHUB",
+ "CHUG",
+ "CHUM",
+ "CITE",
+ "CITY",
+ "CLAD",
+ "CLAM",
+ "CLAN",
+ "CLAW",
+ "CLAY",
+ "CLOD",
+ "CLOG",
+ "CLOT",
+ "CLUB",
+ "CLUE",
+ "COAL",
+ "COAT",
+ "COCA",
+ "COCK",
+ "COCO",
+ "CODA",
+ "CODE",
+ "CODY",
+ "COED",
+ "COIL",
+ "COIN",
+ "COKE",
+ "COLA",
+ "COLD",
+ "COLT",
+ "COMA",
+ "COMB",
+ "COME",
+ "COOK",
+ "COOL",
+ "COON",
+ "COOT",
+ "CORD",
+ "CORE",
+ "CORK",
+ "CORN",
+ "COST",
+ "COVE",
+ "COWL",
+ "CRAB",
+ "CRAG",
+ "CRAM",
+ "CRAY",
+ "CREW",
+ "CRIB",
+ "CROW",
+ "CRUD",
+ "CUBA",
+ "CUBE",
+ "CUFF",
+ "CULL",
+ "CULT",
+ "CUNY",
+ "CURB",
+ "CURD",
+ "CURE",
+ "CURL",
+ "CURT",
+ "CUTS",
+ "DADE",
+ "DALE",
+ "DAME",
+ "DANA",
+ "DANE",
+ "DANG",
+ "DANK",
+ "DARE",
+ "DARK",
+ "DARN",
+ "DART",
+ "DASH",
+ "DATA",
+ "DATE",
+ "DAVE",
+ "DAVY",
+ "DAWN",
+ "DAYS",
+ "DEAD",
+ "DEAF",
+ "DEAL",
+ "DEAN",
+ "DEAR",
+ "DEBT",
+ "DECK",
+ "DEED",
+ "DEEM",
+ "DEER",
+ "DEFT",
+ "DEFY",
+ "DELL",
+ "DENT",
+ "DENY",
+ "DESK",
+ "DIAL",
+ "DICE",
+ "DIED",
+ "DIET",
+ "DIME",
+ "DINE",
+ "DING",
+ "DINT",
+ "DIRE",
+ "DIRT",
+ "DISC",
+ "DISH",
+ "DISK",
+ "DIVE",
+ "DOCK",
+ "DOES",
+ "DOLE",
+ "DOLL",
+ "DOLT",
+ "DOME",
+ "DONE",
+ "DOOM",
+ "DOOR",
+ "DORA",
+ "DOSE",
+ "DOTE",
+ "DOUG",
+ "DOUR",
+ "DOVE",
+ "DOWN",
+ "DRAB",
+ "DRAG",
+ "DRAM",
+ "DRAW",
+ "DREW",
+ "DRUB",
+ "DRUG",
+ "DRUM",
+ "DUAL",
+ "DUCK",
+ "DUCT",
+ "DUEL",
+ "DUET",
+ "DUKE",
+ "DULL",
+ "DUMB",
+ "DUNE",
+ "DUNK",
+ "DUSK",
+ "DUST",
+ "DUTY",
+ "EACH",
+ "EARL",
+ "EARN",
+ "EASE",
+ "EAST",
+ "EASY",
+ "EBEN",
+ "ECHO",
+ "EDDY",
+ "EDEN",
+ "EDGE",
+ "EDGY",
+ "EDIT",
+ "EDNA",
+ "EGAN",
+ "ELAN",
+ "ELBA",
+ "ELLA",
+ "ELSE",
+ "EMIL",
+ "EMIT",
+ "EMMA",
+ "ENDS",
+ "ERIC",
+ "EROS",
+ "EVEN",
+ "EVER",
+ "EVIL",
+ "EYED",
+ "FACE",
+ "FACT",
+ "FADE",
+ "FAIL",
+ "FAIN",
+ "FAIR",
+ "FAKE",
+ "FALL",
+ "FAME",
+ "FANG",
+ "FARM",
+ "FAST",
+ "FATE",
+ "FAWN",
+ "FEAR",
+ "FEAT",
+ "FEED",
+ "FEEL",
+ "FEET",
+ "FELL",
+ "FELT",
+ "FEND",
+ "FERN",
+ "FEST",
+ "FEUD",
+ "FIEF",
+ "FIGS",
+ "FILE",
+ "FILL",
+ "FILM",
+ "FIND",
+ "FINE",
+ "FINK",
+ "FIRE",
+ "FIRM",
+ "FISH",
+ "FISK",
+ "FIST",
+ "FITS",
+ "FIVE",
+ "FLAG",
+ "FLAK",
+ "FLAM",
+ "FLAT",
+ "FLAW",
+ "FLEA",
+ "FLED",
+ "FLEW",
+ "FLIT",
+ "FLOC",
+ "FLOG",
+ "FLOW",
+ "FLUB",
+ "FLUE",
+ "FOAL",
+ "FOAM",
+ "FOGY",
+ "FOIL",
+ "FOLD",
+ "FOLK",
+ "FOND",
+ "FONT",
+ "FOOD",
+ "FOOL",
+ "FOOT",
+ "FORD",
+ "FORE",
+ "FORK",
+ "FORM",
+ "FORT",
+ "FOSS",
+ "FOUL",
+ "FOUR",
+ "FOWL",
+ "FRAU",
+ "FRAY",
+ "FRED",
+ "FREE",
+ "FRET",
+ "FREY",
+ "FROG",
+ "FROM",
+ "FUEL",
+ "FULL",
+ "FUME",
+ "FUND",
+ "FUNK",
+ "FURY",
+ "FUSE",
+ "FUSS",
+ "GAFF",
+ "GAGE",
+ "GAIL",
+ "GAIN",
+ "GAIT",
+ "GALA",
+ "GALE",
+ "GALL",
+ "GALT",
+ "GAME",
+ "GANG",
+ "GARB",
+ "GARY",
+ "GASH",
+ "GATE",
+ "GAUL",
+ "GAUR",
+ "GAVE",
+ "GAWK",
+ "GEAR",
+ "GELD",
+ "GENE",
+ "GENT",
+ "GERM",
+ "GETS",
+ "GIBE",
+ "GIFT",
+ "GILD",
+ "GILL",
+ "GILT",
+ "GINA",
+ "GIRD",
+ "GIRL",
+ "GIST",
+ "GIVE",
+ "GLAD",
+ "GLEE",
+ "GLEN",
+ "GLIB",
+ "GLOB",
+ "GLOM",
+ "GLOW",
+ "GLUE",
+ "GLUM",
+ "GLUT",
+ "GOAD",
+ "GOAL",
+ "GOAT",
+ "GOER",
+ "GOES",
+ "GOLD",
+ "GOLF",
+ "GONE",
+ "GONG",
+ "GOOD",
+ "GOOF",
+ "GORE",
+ "GORY",
+ "GOSH",
+ "GOUT",
+ "GOWN",
+ "GRAB",
+ "GRAD",
+ "GRAY",
+ "GREG",
+ "GREW",
+ "GREY",
+ "GRID",
+ "GRIM",
+ "GRIN",
+ "GRIT",
+ "GROW",
+ "GRUB",
+ "GULF",
+ "GULL",
+ "GUNK",
+ "GURU",
+ "GUSH",
+ "GUST",
+ "GWEN",
+ "GWYN",
+ "HAAG",
+ "HAAS",
+ "HACK",
+ "HAIL",
+ "HAIR",
+ "HALE",
+ "HALF",
+ "HALL",
+ "HALO",
+ "HALT",
+ "HAND",
+ "HANG",
+ "HANK",
+ "HANS",
+ "HARD",
+ "HARK",
+ "HARM",
+ "HART",
+ "HASH",
+ "HAST",
+ "HATE",
+ "HATH",
+ "HAUL",
+ "HAVE",
+ "HAWK",
+ "HAYS",
+ "HEAD",
+ "HEAL",
+ "HEAR",
+ "HEAT",
+ "HEBE",
+ "HECK",
+ "HEED",
+ "HEEL",
+ "HEFT",
+ "HELD",
+ "HELL",
+ "HELM",
+ "HERB",
+ "HERD",
+ "HERE",
+ "HERO",
+ "HERS",
+ "HESS",
+ "HEWN",
+ "HICK",
+ "HIDE",
+ "HIGH",
+ "HIKE",
+ "HILL",
+ "HILT",
+ "HIND",
+ "HINT",
+ "HIRE",
+ "HISS",
+ "HIVE",
+ "HOBO",
+ "HOCK",
+ "HOFF",
+ "HOLD",
+ "HOLE",
+ "HOLM",
+ "HOLT",
+ "HOME",
+ "HONE",
+ "HONK",
+ "HOOD",
+ "HOOF",
+ "HOOK",
+ "HOOT",
+ "HORN",
+ "HOSE",
+ "HOST",
+ "HOUR",
+ "HOVE",
+ "HOWE",
+ "HOWL",
+ "HOYT",
+ "HUCK",
+ "HUED",
+ "HUFF",
+ "HUGE",
+ "HUGH",
+ "HUGO",
+ "HULK",
+ "HULL",
+ "HUNK",
+ "HUNT",
+ "HURD",
+ "HURL",
+ "HURT",
+ "HUSH",
+ "HYDE",
+ "HYMN",
+ "IBIS",
+ "ICON",
+ "IDEA",
+ "IDLE",
+ "IFFY",
+ "INCA",
+ "INCH",
+ "INTO",
+ "IONS",
+ "IOTA",
+ "IOWA",
+ "IRIS",
+ "IRMA",
+ "IRON",
+ "ISLE",
+ "ITCH",
+ "ITEM",
+ "IVAN",
+ "JACK",
+ "JADE",
+ "JAIL",
+ "JAKE",
+ "JANE",
+ "JAVA",
+ "JEAN",
+ "JEFF",
+ "JERK",
+ "JESS",
+ "JEST",
+ "JIBE",
+ "JILL",
+ "JILT",
+ "JIVE",
+ "JOAN",
+ "JOBS",
+ "JOCK",
+ "JOEL",
+ "JOEY",
+ "JOHN",
+ "JOIN",
+ "JOKE",
+ "JOLT",
+ "JOVE",
+ "JUDD",
+ "JUDE",
+ "JUDO",
+ "JUDY",
+ "JUJU",
+ "JUKE",
+ "JULY",
+ "JUNE",
+ "JUNK",
+ "JUNO",
+ "JURY",
+ "JUST",
+ "JUTE",
+ "KAHN",
+ "KALE",
+ "KANE",
+ "KANT",
+ "KARL",
+ "KATE",
+ "KEEL",
+ "KEEN",
+ "KENO",
+ "KENT",
+ "KERN",
+ "KERR",
+ "KEYS",
+ "KICK",
+ "KILL",
+ "KIND",
+ "KING",
+ "KIRK",
+ "KISS",
+ "KITE",
+ "KLAN",
+ "KNEE",
+ "KNEW",
+ "KNIT",
+ "KNOB",
+ "KNOT",
+ "KNOW",
+ "KOCH",
+ "KONG",
+ "KUDO",
+ "KURD",
+ "KURT",
+ "KYLE",
+ "LACE",
+ "LACK",
+ "LACY",
+ "LADY",
+ "LAID",
+ "LAIN",
+ "LAIR",
+ "LAKE",
+ "LAMB",
+ "LAME",
+ "LAND",
+ "LANE",
+ "LANG",
+ "LARD",
+ "LARK",
+ "LASS",
+ "LAST",
+ "LATE",
+ "LAUD",
+ "LAVA",
+ "LAWN",
+ "LAWS",
+ "LAYS",
+ "LEAD",
+ "LEAF",
+ "LEAK",
+ "LEAN",
+ "LEAR",
+ "LEEK",
+ "LEER",
+ "LEFT",
+ "LEND",
+ "LENS",
+ "LENT",
+ "LEON",
+ "LESK",
+ "LESS",
+ "LEST",
+ "LETS",
+ "LIAR",
+ "LICE",
+ "LICK",
+ "LIED",
+ "LIEN",
+ "LIES",
+ "LIEU",
+ "LIFE",
+ "LIFT",
+ "LIKE",
+ "LILA",
+ "LILT",
+ "LILY",
+ "LIMA",
+ "LIMB",
+ "LIME",
+ "LIND",
+ "LINE",
+ "LINK",
+ "LINT",
+ "LION",
+ "LISA",
+ "LIST",
+ "LIVE",
+ "LOAD",
+ "LOAF",
+ "LOAM",
+ "LOAN",
+ "LOCK",
+ "LOFT",
+ "LOGE",
+ "LOIS",
+ "LOLA",
+ "LONE",
+ "LONG",
+ "LOOK",
+ "LOON",
+ "LOOT",
+ "LORD",
+ "LORE",
+ "LOSE",
+ "LOSS",
+ "LOST",
+ "LOUD",
+ "LOVE",
+ "LOWE",
+ "LUCK",
+ "LUCY",
+ "LUGE",
+ "LUKE",
+ "LULU",
+ "LUND",
+ "LUNG",
+ "LURA",
+ "LURE",
+ "LURK",
+ "LUSH",
+ "LUST",
+ "LYLE",
+ "LYNN",
+ "LYON",
+ "LYRA",
+ "MACE",
+ "MADE",
+ "MAGI",
+ "MAID",
+ "MAIL",
+ "MAIN",
+ "MAKE",
+ "MALE",
+ "MALI",
+ "MALL",
+ "MALT",
+ "MANA",
+ "MANN",
+ "MANY",
+ "MARC",
+ "MARE",
+ "MARK",
+ "MARS",
+ "MART",
+ "MARY",
+ "MASH",
+ "MASK",
+ "MASS",
+ "MAST",
+ "MATE",
+ "MATH",
+ "MAUL",
+ "MAYO",
+ "MEAD",
+ "MEAL",
+ "MEAN",
+ "MEAT",
+ "MEEK",
+ "MEET",
+ "MELD",
+ "MELT",
+ "MEMO",
+ "MEND",
+ "MENU",
+ "MERT",
+ "MESH",
+ "MESS",
+ "MICE",
+ "MIKE",
+ "MILD",
+ "MILE",
+ "MILK",
+ "MILL",
+ "MILT",
+ "MIMI",
+ "MIND",
+ "MINE",
+ "MINI",
+ "MINK",
+ "MINT",
+ "MIRE",
+ "MISS",
+ "MIST",
+ "MITE",
+ "MITT",
+ "MOAN",
+ "MOAT",
+ "MOCK",
+ "MODE",
+ "MOLD",
+ "MOLE",
+ "MOLL",
+ "MOLT",
+ "MONA",
+ "MONK",
+ "MONT",
+ "MOOD",
+ "MOON",
+ "MOOR",
+ "MOOT",
+ "MORE",
+ "MORN",
+ "MORT",
+ "MOSS",
+ "MOST",
+ "MOTH",
+ "MOVE",
+ "MUCH",
+ "MUCK",
+ "MUDD",
+ "MUFF",
+ "MULE",
+ "MULL",
+ "MURK",
+ "MUSH",
+ "MUST",
+ "MUTE",
+ "MUTT",
+ "MYRA",
+ "MYTH",
+ "NAGY",
+ "NAIL",
+ "NAIR",
+ "NAME",
+ "NARY",
+ "NASH",
+ "NAVE",
+ "NAVY",
+ "NEAL",
+ "NEAR",
+ "NEAT",
+ "NECK",
+ "NEED",
+ "NEIL",
+ "NELL",
+ "NEON",
+ "NERO",
+ "NESS",
+ "NEST",
+ "NEWS",
+ "NEWT",
+ "NIBS",
+ "NICE",
+ "NICK",
+ "NILE",
+ "NINA",
+ "NINE",
+ "NOAH",
+ "NODE",
+ "NOEL",
+ "NOLL",
+ "NONE",
+ "NOOK",
+ "NOON",
+ "NORM",
+ "NOSE",
+ "NOTE",
+ "NOUN",
+ "NOVA",
+ "NUDE",
+ "NULL",
+ "NUMB",
+ "OATH",
+ "OBEY",
+ "OBOE",
+ "ODIN",
+ "OHIO",
+ "OILY",
+ "OINT",
+ "OKAY",
+ "OLAF",
+ "OLDY",
+ "OLGA",
+ "OLIN",
+ "OMAN",
+ "OMEN",
+ "OMIT",
+ "ONCE",
+ "ONES",
+ "ONLY",
+ "ONTO",
+ "ONUS",
+ "ORAL",
+ "ORGY",
+ "OSLO",
+ "OTIS",
+ "OTTO",
+ "OUCH",
+ "OUST",
+ "OUTS",
+ "OVAL",
+ "OVEN",
+ "OVER",
+ "OWLY",
+ "OWNS",
+ "QUAD",
+ "QUIT",
+ "QUOD",
+ "RACE",
+ "RACK",
+ "RACY",
+ "RAFT",
+ "RAGE",
+ "RAID",
+ "RAIL",
+ "RAIN",
+ "RAKE",
+ "RANK",
+ "RANT",
+ "RARE",
+ "RASH",
+ "RATE",
+ "RAVE",
+ "RAYS",
+ "READ",
+ "REAL",
+ "REAM",
+ "REAR",
+ "RECK",
+ "REED",
+ "REEF",
+ "REEK",
+ "REEL",
+ "REID",
+ "REIN",
+ "RENA",
+ "REND",
+ "RENT",
+ "REST",
+ "RICE",
+ "RICH",
+ "RICK",
+ "RIDE",
+ "RIFT",
+ "RILL",
+ "RIME",
+ "RING",
+ "RINK",
+ "RISE",
+ "RISK",
+ "RITE",
+ "ROAD",
+ "ROAM",
+ "ROAR",
+ "ROBE",
+ "ROCK",
+ "RODE",
+ "ROIL",
+ "ROLL",
+ "ROME",
+ "ROOD",
+ "ROOF",
+ "ROOK",
+ "ROOM",
+ "ROOT",
+ "ROSA",
+ "ROSE",
+ "ROSS",
+ "ROSY",
+ "ROTH",
+ "ROUT",
+ "ROVE",
+ "ROWE",
+ "ROWS",
+ "RUBE",
+ "RUBY",
+ "RUDE",
+ "RUDY",
+ "RUIN",
+ "RULE",
+ "RUNG",
+ "RUNS",
+ "RUNT",
+ "RUSE",
+ "RUSH",
+ "RUSK",
+ "RUSS",
+ "RUST",
+ "RUTH",
+ "SACK",
+ "SAFE",
+ "SAGE",
+ "SAID",
+ "SAIL",
+ "SALE",
+ "SALK",
+ "SALT",
+ "SAME",
+ "SAND",
+ "SANE",
+ "SANG",
+ "SANK",
+ "SARA",
+ "SAUL",
+ "SAVE",
+ "SAYS",
+ "SCAN",
+ "SCAR",
+ "SCAT",
+ "SCOT",
+ "SEAL",
+ "SEAM",
+ "SEAR",
+ "SEAT",
+ "SEED",
+ "SEEK",
+ "SEEM",
+ "SEEN",
+ "SEES",
+ "SELF",
+ "SELL",
+ "SEND",
+ "SENT",
+ "SETS",
+ "SEWN",
+ "SHAG",
+ "SHAM",
+ "SHAW",
+ "SHAY",
+ "SHED",
+ "SHIM",
+ "SHIN",
+ "SHOD",
+ "SHOE",
+ "SHOT",
+ "SHOW",
+ "SHUN",
+ "SHUT",
+ "SICK",
+ "SIDE",
+ "SIFT",
+ "SIGH",
+ "SIGN",
+ "SILK",
+ "SILL",
+ "SILO",
+ "SILT",
+ "SINE",
+ "SING",
+ "SINK",
+ "SIRE",
+ "SITE",
+ "SITS",
+ "SITU",
+ "SKAT",
+ "SKEW",
+ "SKID",
+ "SKIM",
+ "SKIN",
+ "SKIT",
+ "SLAB",
+ "SLAM",
+ "SLAT",
+ "SLAY",
+ "SLED",
+ "SLEW",
+ "SLID",
+ "SLIM",
+ "SLIT",
+ "SLOB",
+ "SLOG",
+ "SLOT",
+ "SLOW",
+ "SLUG",
+ "SLUM",
+ "SLUR",
+ "SMOG",
+ "SMUG",
+ "SNAG",
+ "SNOB",
+ "SNOW",
+ "SNUB",
+ "SNUG",
+ "SOAK",
+ "SOAR",
+ "SOCK",
+ "SODA",
+ "SOFA",
+ "SOFT",
+ "SOIL",
+ "SOLD",
+ "SOME",
+ "SONG",
+ "SOON",
+ "SOOT",
+ "SORE",
+ "SORT",
+ "SOUL",
+ "SOUR",
+ "SOWN",
+ "STAB",
+ "STAG",
+ "STAN",
+ "STAR",
+ "STAY",
+ "STEM",
+ "STEW",
+ "STIR",
+ "STOW",
+ "STUB",
+ "STUN",
+ "SUCH",
+ "SUDS",
+ "SUIT",
+ "SULK",
+ "SUMS",
+ "SUNG",
+ "SUNK",
+ "SURE",
+ "SURF",
+ "SWAB",
+ "SWAG",
+ "SWAM",
+ "SWAN",
+ "SWAT",
+ "SWAY",
+ "SWIM",
+ "SWUM",
+ "TACK",
+ "TACT",
+ "TAIL",
+ "TAKE",
+ "TALE",
+ "TALK",
+ "TALL",
+ "TANK",
+ "TASK",
+ "TATE",
+ "TAUT",
+ "TEAL",
+ "TEAM",
+ "TEAR",
+ "TECH",
+ "TEEM",
+ "TEEN",
+ "TEET",
+ "TELL",
+ "TEND",
+ "TENT",
+ "TERM",
+ "TERN",
+ "TESS",
+ "TEST",
+ "THAN",
+ "THAT",
+ "THEE",
+ "THEM",
+ "THEN",
+ "THEY",
+ "THIN",
+ "THIS",
+ "THUD",
+ "THUG",
+ "TICK",
+ "TIDE",
+ "TIDY",
+ "TIED",
+ "TIER",
+ "TILE",
+ "TILL",
+ "TILT",
+ "TIME",
+ "TINA",
+ "TINE",
+ "TINT",
+ "TINY",
+ "TIRE",
+ "TOAD",
+ "TOGO",
+ "TOIL",
+ "TOLD",
+ "TOLL",
+ "TONE",
+ "TONG",
+ "TONY",
+ "TOOK",
+ "TOOL",
+ "TOOT",
+ "TORE",
+ "TORN",
+ "TOTE",
+ "TOUR",
+ "TOUT",
+ "TOWN",
+ "TRAG",
+ "TRAM",
+ "TRAY",
+ "TREE",
+ "TREK",
+ "TRIG",
+ "TRIM",
+ "TRIO",
+ "TROD",
+ "TROT",
+ "TROY",
+ "TRUE",
+ "TUBA",
+ "TUBE",
+ "TUCK",
+ "TUFT",
+ "TUNA",
+ "TUNE",
+ "TUNG",
+ "TURF",
+ "TURN",
+ "TUSK",
+ "TWIG",
+ "TWIN",
+ "TWIT",
+ "ULAN",
+ "UNIT",
+ "URGE",
+ "USED",
+ "USER",
+ "USES",
+ "UTAH",
+ "VAIL",
+ "VAIN",
+ "VALE",
+ "VARY",
+ "VASE",
+ "VAST",
+ "VEAL",
+ "VEDA",
+ "VEIL",
+ "VEIN",
+ "VEND",
+ "VENT",
+ "VERB",
+ "VERY",
+ "VETO",
+ "VICE",
+ "VIEW",
+ "VINE",
+ "VISE",
+ "VOID",
+ "VOLT",
+ "VOTE",
+ "WACK",
+ "WADE",
+ "WAGE",
+ "WAIL",
+ "WAIT",
+ "WAKE",
+ "WALE",
+ "WALK",
+ "WALL",
+ "WALT",
+ "WAND",
+ "WANE",
+ "WANG",
+ "WANT",
+ "WARD",
+ "WARM",
+ "WARN",
+ "WART",
+ "WASH",
+ "WAST",
+ "WATS",
+ "WATT",
+ "WAVE",
+ "WAVY",
+ "WAYS",
+ "WEAK",
+ "WEAL",
+ "WEAN",
+ "WEAR",
+ "WEED",
+ "WEEK",
+ "WEIR",
+ "WELD",
+ "WELL",
+ "WELT",
+ "WENT",
+ "WERE",
+ "WERT",
+ "WEST",
+ "WHAM",
+ "WHAT",
+ "WHEE",
+ "WHEN",
+ "WHET",
+ "WHOA",
+ "WHOM",
+ "WICK",
+ "WIFE",
+ "WILD",
+ "WILL",
+ "WIND",
+ "WINE",
+ "WING",
+ "WINK",
+ "WINO",
+ "WIRE",
+ "WISE",
+ "WISH",
+ "WITH",
+ "WOLF",
+ "WONT",
+ "WOOD",
+ "WOOL",
+ "WORD",
+ "WORE",
+ "WORK",
+ "WORM",
+ "WORN",
+ "WOVE",
+ "WRIT",
+ "WYNN",
+ "YALE",
+ "YANG",
+ "YANK",
+ "YARD",
+ "YARN",
+ "YAWL",
+ "YAWN",
+ "YEAH",
+ "YEAR",
+ "YELL",
+ "YOGA",
+ "YOKE"
+};
+
+/* Encode 8 bytes in 'c' as a string of English words. */
+char *opiebtoe FUNCTION((engout, c), char *engout AND char *c)
+{
+ char cp[9]; /* add in room for the parity 2 bits */
+ int p, i;
+
+ engout[0] = '\0';
+ memcpy(cp, c, 8);
+ /* compute parity */
+ for (p = 0, i = 0; i < 64; i += 2)
+ p += extract(cp, i, 2);
+
+ cp[8] = (char)(p << 6);
+ strncat(engout, Wp[extract(cp, 0, 11)], 4);
+ strcat(engout, " ");
+ strncat(engout, Wp[extract(cp, 11, 11)], 4);
+ strcat(engout, " ");
+ strncat(engout, Wp[extract(cp, 22, 11)], 4);
+ strcat(engout, " ");
+ strncat(engout, Wp[extract(cp, 33, 11)], 4);
+ strcat(engout, " ");
+ strncat(engout, Wp[extract(cp, 44, 11)], 4);
+ strcat(engout, " ");
+ strncat(engout, Wp[extract(cp, 55, 11)], 4);
+ return (engout);
+}
+
+/* convert English to binary
+ * returns 1 OK - all good words and parity is OK
+ * 0 word not in data base
+ * -1 badly formed in put ie > 4 char word
+ * -2 words OK but parity is wrong
+ */
+int opieetob FUNCTION((out, e), char *out AND char *e)
+{
+ char *word, *c, *input, b[9];
+ int i, p, v, l, low, high, rval = -1;
+
+ if (e == NULL)
+ return -1;
+
+ if ((i = strlen(e)) > 64)
+ i = 64;
+
+ if (!(input = malloc(i+1)))
+ return -1;
+
+ strncpy(input, e, i);
+ input[i] = 0;
+ memset(b, 0, sizeof(b));
+ memset(out, 0, 8);
+
+ for (i = 0, p = 0, word = c = input; i < 6; i++, p += 11) {
+ while (*c && !isalpha(*c)) c++;
+ word = c;
+ while (*c) {
+ if (islower(*c))
+ *c = toupper(*c);
+ if (*c == '1')
+ *c = 'L';
+ if (*c == '0')
+ *c = 'O';
+ if (*c == '5')
+ *c = 'S';
+ if (!isalpha(*c))
+ break;
+ c++;
+ }
+ if ((!*c) && (i != 5))
+ goto opiebtoeret;
+ *c = 0;
+ c++;
+ if (c == word)
+ goto opiebtoeret;
+ l = strlen(word);
+ if (l > 4 || l < 1)
+ goto opiebtoeret;
+ if (l < 4) {
+ low = 0;
+ high = 570;
+ } else {
+ low = 571;
+ high = 2047;
+ }
+ if ((v = wsrch(word, low, high)) < 0) {
+ rval = 0;
+ goto opiebtoeret;
+ }
+ insert(b, v, p, 11);
+ }
+
+ /* now check the parity of what we got */
+ for (p = 0, i = 0; i < 64; i += 2)
+ p += extract(b, i, 2);
+
+ if ((p & 3) != extract(b, 64, 2)) {
+ rval = -2;
+ goto opiebtoeret;
+ }
+
+ memcpy(out, b, 8);
+
+ rval = 1;
+
+opiebtoeret:
+ free(input);
+ return rval;
+}
+
+/* Internal subroutines for word encoding/decoding */
+
+/* Dictionary binary search */
+static int wsrch FUNCTION((w, low, high), char *w AND int low AND int high)
+{
+ int i, j;
+
+ for (;;) {
+ i = (low + high) / 2;
+ if ((j = strncmp(w, Wp[i], 4)) == 0)
+ return i; /* Found it */
+ if (high == low + 1) {
+ /* Avoid effects of integer truncation in /2 */
+ if (strncmp(w, Wp[high], 4) == 0)
+ return high;
+ else
+ return -1;
+ }
+ if (low >= high)
+ return -1; /* I don't *think* this can happen... */
+ if (j < 0)
+ high = i; /* Search lower half */
+ else
+ low = i; /* Search upper half */
+ }
+}
+
+static VOIDRET insert FUNCTION((s, x, start, length), char *s AND int x AND int start AND int length)
+{
+ unsigned char cl;
+ unsigned char cc;
+ unsigned char cr;
+ UINT4 y;
+ int shift;
+
+ shift = ((8 - ((start + length) % 8)) % 8);
+ y = (long) x << shift;
+ cl = (y >> 16) & 0xff;
+ cc = (y >> 8) & 0xff;
+ cr = y & 0xff;
+ if (shift + length > 16) {
+ s[start / 8] |= cl;
+ s[start / 8 + 1] |= cc;
+ s[start / 8 + 2] |= cr;
+ } else
+ if (shift + length > 8) {
+ s[start / 8] |= cc;
+ s[start / 8 + 1] |= cr;
+ } else {
+ s[start / 8] |= cr;
+ }
+}
+
+static UINT4 extract FUNCTION((s, start, length), char *s AND int start AND int length)
+{
+ UINT4 x;
+ unsigned char cl;
+ unsigned char cc;
+ unsigned char cr;
+
+ cl = s[start / 8];
+ cc = s[start / 8 + 1];
+ cr = s[start / 8 + 2];
+ x = ((UINT4) (cl << 8 | cc) << 8 | cr);
+ x = x >> (24 - (length + (start % 8)));
+ x = (x & (0xffff >> (16 - length)));
+ return (x);
+}
diff --git a/contrib/opie/libopie/btoh.c b/contrib/opie/libopie/btoh.c
new file mode 100644
index 0000000..68cf75f
--- /dev/null
+++ b/contrib/opie/libopie/btoh.c
@@ -0,0 +1,35 @@
+/* btoh.c: The opiebtoh() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+static char hextochar[16] =
+{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+char *opiebtoh FUNCTION((out, in), char *out AND char *in)
+{
+ int i;
+ char *c = out;
+
+ for (i = 0; i < 4; i++) {
+ *(c++) = hextochar[((*in) >> 4) & 0x0f];
+ *(c++) = hextochar[(*in++) & 0x0f];
+ *(c++) = hextochar[((*in) >> 4) & 0x0f];
+ *(c++) = hextochar[(*in++) & 0x0f];
+ *(c++) = ' ';
+ }
+ *(--c) = 0;
+
+ return out;
+}
diff --git a/contrib/opie/libopie/challenge.c b/contrib/opie/libopie/challenge.c
new file mode 100644
index 0000000..d67d495
--- /dev/null
+++ b/contrib/opie/libopie/challenge.c
@@ -0,0 +1,74 @@
+/* challenge.c: The opiechallenge() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Use opie_ prefix. Send debug info to
+ syslog. Add sha plumbing.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Created at NRL for OPIE 2.2 from opiesubr2.c
+*/
+#include "opie_cfg.h"
+#include <stdio.h>
+#include <string.h>
+#if DEBUG
+#include <syslog.h>
+#endif /* DEBUG */
+#include "opie.h"
+
+/* Return an OTP challenge string for user 'name'.
+
+ The return values are:
+
+ 0 = All good
+ -1 = Low-level error (file, memory, I/O, etc.)
+ 1 = High-level error (user not found or locked)
+
+ This function MUST eventually be followed by an opieverify() to release
+ the user lock and file handles.
+
+ This function will give you a blanked-out state block if it returns a
+ nonzero status. Even though it returns a non-zero status and a blank
+ state block, you still MUST call opieverify() to clear the lock and
+ any internal state (the latter condition is not actually used yet).
+*/
+
+static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
+
+int opiechallenge FUNCTION((mp, name, ss), struct opie *mp AND char *name AND char *ss)
+{
+ int rval = -1;
+
+ memset(mp, 0, sizeof(*mp));
+
+ rval = opielookup(mp, name);
+#if DEBUG
+ if (rval) syslog(LOG_DEBUG, "opiechallenge: opielookup(mp, name=%s) returned %d", name, rval);
+#endif /* DEBUG */
+
+ if (!rval) {
+ rval = opielock(name);
+#if DEBUG
+ if (rval) syslog(LOG_DEBUG, "opiechallenge: opielock(name=%s) returned %d", name, rval);
+#endif /* DEBUG */
+ }
+
+ if (rval) {
+ opierandomchallenge(ss);
+ memset(mp, 0, sizeof(*mp));
+ } else
+ sprintf(ss, "otp-%s %d %s", algids[MDX], mp->opie_n - 1, mp->opie_seed);
+
+ return rval;
+}
diff --git a/contrib/opie/libopie/generator.c b/contrib/opie/libopie/generator.c
new file mode 100644
index 0000000..ccd67c7
--- /dev/null
+++ b/contrib/opie/libopie/generator.c
@@ -0,0 +1,110 @@
+/* generator.c: The opiegenerator() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Use _opieparsechallenge(). ifdef
+ around string.h. Output hex responses by default, output
+ OTP re-init extended responses (same secret) if sequence
+ number falls below 10.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Bug fixes.
+ Created at NRL for OPIE 2.2.
+*/
+
+#include "opie_cfg.h"
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include "opie.h"
+
+static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
+
+int opiegenerator FUNCTION((buffer, secret, response), char *buffer AND char *secret AND char *response)
+{
+ int algorithm;
+ int sequence;
+ char *seed;
+ char key[8];
+ int i;
+
+ if (!(buffer = strstr(buffer, "otp-")))
+ return 1;
+
+ buffer += 4;
+
+ if (_opieparsechallenge(buffer, &algorithm, &sequence, &seed))
+ return 1;
+
+ if ((sequence < 2) || (sequence > 9999))
+ return 1;
+
+ if (opiepasscheck(secret))
+ return -2;
+
+ if (i = opiekeycrunch(algorithm, key, seed, secret))
+ return i;
+
+ if (sequence < 10) {
+ char newseed[OPIE_SEED_MAX + 1];
+ char newkey[8], cko[8], ckn[8], ckxor[8], cv[8];
+ char *c;
+ char buf[OPIE_SEED_MAX + 48 + 1];
+
+ if (opienewseed(strcpy(newseed, seed)) < 0)
+ return -1;
+
+ if (opiekeycrunch(algorithm, newkey, newseed, secret))
+ return -1;
+
+ for (i = 0; i < 499; i++)
+ opiehash(newkey, algorithm);
+
+ if (opiekeycrunch(algorithm | 0x10, cko, seed, secret))
+ return -1;
+
+ if (opiekeycrunch(algorithm | 0x10, ckn, newseed, secret))
+ return -1;
+
+ for (i = 0; i < 8; i++)
+ ckxor[i] = cko[i] ^ ckn[i];
+
+ strcpy(response, "init:");
+ strcat(response, opiebtoh(buf, key));
+ sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed);
+ strcat(response, buf);
+ strcat(response, opiebtoh(buf, newkey));
+ strcat(response, ":");
+ strcat(response, opiebtoh(buf, ckxor));
+ strcat(response, ":");
+
+ c = buf;
+ memcpy(c, ckn, sizeof(ckn)); c += sizeof(ckn);
+ memcpy(c, key, sizeof(key)); c += sizeof(key);
+#ifdef HAVE_ANSISPRINTF
+ c += sprintf(c, "%s 499 %s", algids[algorithm], newseed);
+#else /* HAVE_ANSISPRINTF */
+ sprintf(c, "%s 499 %s", algids[algorithm], newseed);
+ while(*c) c++;
+#endif /* HAVE_ANSISPRINTF */
+ memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey);
+ memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor);
+ memcpy(c, ckn, sizeof(ckn)); c += sizeof(ckn);
+ opiehashlen(algorithm, buf, cv, (unsigned int)c - (unsigned int)buf);
+
+ strcat(response, opiebtoh(buf, cv));
+ } else {
+ while (sequence-- != 0)
+ opiehash(key, algorithm);
+
+ opiebtoh(response, key);
+ }
+
+ return 0;
+}
diff --git a/contrib/opie/libopie/getsequence.c b/contrib/opie/libopie/getsequence.c
new file mode 100644
index 0000000..f0a6e78
--- /dev/null
+++ b/contrib/opie/libopie/getsequence.c
@@ -0,0 +1,27 @@
+/* getsequence.c: The opiegetsequence() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Use opie_ prefix.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Created at NRL for OPIE 2.2 from opiesubr2.c
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+int opiegetsequence FUNCTION((stateblock), struct opie *stateblock)
+{
+ return stateblock->opie_n;
+}
diff --git a/contrib/opie/libopie/getutmpentry.c b/contrib/opie/libopie/getutmpentry.c
new file mode 100644
index 0000000..8013f87
--- /dev/null
+++ b/contrib/opie/libopie/getutmpentry.c
@@ -0,0 +1,72 @@
+/* getutmpentry.c: The __opiegetutmpentry() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 (re-write).
+*/
+
+#include "opie_cfg.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <utmp.h>
+
+#if DOUTMPX
+#include <utmpx.h>
+#define getutline(x) getutxline(x)
+#define utmp utmpx
+#endif /* DOUTMPX */
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+
+#if DEBUG
+#include <syslog.h>
+#endif /* DEBUG */
+#include "opie.h"
+
+#if !HAVE_GETUTLINE
+struct utmp *getutline __P((struct utmp *));
+#endif /* HAVE_GETUTLINE */
+
+int __opiegetutmpentry FUNCTION((line, utmp), char *line AND struct utmp *utmp)
+{
+ struct utmp u, *pu;
+
+ memset(&u, 0, sizeof(u));
+
+ if (!strncmp(line, "/dev/", 5)) {
+ strncpy(u.ut_line, line + 5, sizeof(u.ut_line));
+ if ((pu = getutline(&u)))
+ goto gotit;
+
+#ifdef hpux
+ strcpy(u.ut_line, "pty/");
+ strncpy(u.ut_line + 4, line + 5, sizeof(u.ut_line) - 4);
+ if ((pu = getutline(&u)))
+ goto gotit;
+#endif /* hpux */
+ }
+
+ strncpy(u.ut_line, line, sizeof(u.ut_line));
+ if ((pu = getutline(&u)))
+ goto gotit;
+
+#if DEBUG
+ syslog(LOG_DEBUG, "__opiegetutmpentry: failed to find entry for line %s", line);
+#endif /* DEBUG */
+ return -1;
+
+gotit:
+#if DEBUG
+ syslog(LOG_DEBUG, "__opiegetutmpentry: succeeded with line %s", pu->ut_line);
+#endif /* DEBUG */
+ memcpy(utmp, pu, sizeof(struct utmp));
+ return 0;
+}
diff --git a/contrib/opie/libopie/hash.c b/contrib/opie/libopie/hash.c
new file mode 100644
index 0000000..4029fa9
--- /dev/null
+++ b/contrib/opie/libopie/hash.c
@@ -0,0 +1,52 @@
+/* hash.c: The opiehash() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 using the old hash.c as a guide.
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+static struct opiemdx_ctx mdx;
+static UINT4 mdx_tmp[4];
+#if 0
+static SHA_INFO sha;
+#endif /* 0 */
+
+VOIDRET opiehash FUNCTION((x, algorithm), VOIDPTR x AND unsigned algorithm)
+{
+ UINT4 *results = (UINT4 *)x;
+
+ switch(algorithm) {
+#if 0
+ case 3:
+ sha_init(&sha);
+ sha_update(&sha, (BYTE *)x, 8);
+ sha_final(&sha);
+ results[0] = sha.digest[0] ^ sha.digest[2] ^ sha.digest[4];
+ results[1] = sha.digest[1] ^ sha.digest[3] ^ sha.digest[5];
+ break;
+#endif /* 0 */
+ case 4:
+ opiemd4init(&mdx);
+ opiemd4update(&mdx, (unsigned char *)x, 8);
+ opiemd4final((unsigned char *)mdx_tmp, &mdx);
+ results[0] = mdx_tmp[0] ^ mdx_tmp[2];
+ results[1] = mdx_tmp[1] ^ mdx_tmp[3];
+ break;
+ case 5:
+ opiemd5init(&mdx);
+ opiemd5update(&mdx, (unsigned char *)x, 8);
+ opiemd5final((unsigned char *)mdx_tmp, &mdx);
+ results[0] = mdx_tmp[0] ^ mdx_tmp[2];
+ results[1] = mdx_tmp[1] ^ mdx_tmp[3];
+ break;
+ }
+}
diff --git a/contrib/opie/libopie/hashlen.c b/contrib/opie/libopie/hashlen.c
new file mode 100644
index 0000000..110eef4
--- /dev/null
+++ b/contrib/opie/libopie/hashlen.c
@@ -0,0 +1,51 @@
+/* hashlen.c: The opiehashlen() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+VOIDRET opiehashlen FUNCTION((algorithm, in, out, n), int algorithm AND VOIDPTR in AND VOIDPTR out AND int n)
+{
+ UINT4 *results = (UINT4 *)out;
+ struct opiemdx_ctx mdx;
+ UINT4 mdx_tmp[4];
+#if 0
+ SHA_INFO sha;
+#endif /* 0 */
+
+ switch(algorithm) {
+#if 0
+ case 3:
+ sha_init(&sha);
+ sha_update(&sha, (BYTE *)in, n);
+ sha_final(&sha);
+ results[0] = sha.digest[0] ^ sha.digest[2] ^ sha.digest[4];
+ results[1] = sha.digest[1] ^ sha.digest[3] ^ sha.digest[5];
+ break;
+#endif /* 0 */
+ case 4:
+ opiemd4init(&mdx);
+ opiemd4update(&mdx, (unsigned char *)in, n);
+ opiemd4final((unsigned char *)mdx_tmp, &mdx);
+ results[0] = mdx_tmp[0] ^ mdx_tmp[2];
+ results[1] = mdx_tmp[1] ^ mdx_tmp[3];
+ break;
+ case 5:
+ opiemd5init(&mdx);
+ opiemd5update(&mdx, (unsigned char *)in, n);
+ opiemd5final((unsigned char *)mdx_tmp, &mdx);
+ results[0] = mdx_tmp[0] ^ mdx_tmp[2];
+ results[1] = mdx_tmp[1] ^ mdx_tmp[3];
+ break;
+ }
+}
diff --git a/contrib/opie/libopie/insecure.c b/contrib/opie/libopie/insecure.c
new file mode 100644
index 0000000..afab006
--- /dev/null
+++ b/contrib/opie/libopie/insecure.c
@@ -0,0 +1,146 @@
+/* insecure.c: The opieinsecure() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Added result caching. Use
+ __opiegetutmpentry(). Ifdef around ut_host check. Eliminate
+ unused variable.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Allow IP loopback. DISPLAY and ut_host must match exactly,
+ not just the part before the colon. Added work-around for
+ Sun CDE dtterm bug. Leave the environment as it was
+ found. Use uname().
+ Created at NRL for OPIE 2.2 from opiesubr.c. Fixed pointer
+ assignment that should have been a comparison.
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* ANSI C standard library */
+#include <sys/param.h>
+#include <unistd.h>
+
+#include <utmp.h>
+#if DOUTMPX
+#include <utmpx.h>
+#define utmp utmpx
+#endif /* DOUTMPX */
+
+#if HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif /* HAVE_SYS_UTSNAME_H */
+
+#include "opie.h"
+
+int opieinsecure FUNCTION_NOARGS
+{
+#ifndef NO_INSECURE_CHECK
+ char *display_name;
+ char *s;
+ char *term_name;
+ int insecure = 0;
+#if HAVE_UT_HOST
+ struct utmp utmp;
+#endif /* HAVE_UT_HOST */
+ static int result = -1;
+
+ if (result != -1)
+ return result;
+
+ display_name = (char *) getenv("DISPLAY");
+ term_name = (char *) getenv("TERM");
+
+ if (display_name) {
+ insecure = 1;
+ if (s = strchr(display_name, ':')) {
+ int n = s - display_name;
+ if (!n)
+ insecure = 0;
+ else {
+ if (!strncmp("unix", display_name, n))
+ insecure = 0;
+ else if (!strncmp("localhost", display_name, n))
+ insecure = 0;
+ else if (!strncmp("loopback", display_name, n))
+ insecure = 0;
+ else if (!strncmp("127.0.0.1", display_name, n))
+ insecure = 0;
+ else {
+ struct utsname utsname;
+
+ if (!uname(&utsname)) {
+ if (!strncmp(utsname.nodename, display_name, n))
+ insecure = 0;
+ else {
+ if (s = strchr(display_name, '.')) {
+ int n2 = s - display_name;
+ if (n < n2)
+ n2 = n;
+ if (!strncmp(utsname.nodename, display_name, n))
+ insecure = 0;
+ } /* endif display_name is '.' */
+ } /* endif hostname != display_name */
+ } /* endif was able to get hostname */
+ } /* endif display_name == UNIX */
+ }
+ }
+ } /* endif display_name == ":" */
+ if (insecure)
+ return (result = 1);
+
+ /* If no DISPLAY variable exists and TERM=xterm,
+ then we probably have an xterm executing on a remote system
+ with an rlogin or telnet to our system. If it were a local
+ xterm, then the DISPLAY environment variable would
+ have to exist. rja */
+ if (!display_name && !term_name && !strcmp("xterm", term_name))
+ return (result = 1);
+
+#if HAVE_UT_HOST
+ memset(&utmp, 0, sizeof(struct utmp));
+ if (!__opiegetutmpentry(ttyname(0), &utmp) && utmp.ut_host[0]) {
+ insecure = 1;
+
+ if (s = strchr(utmp.ut_host, ':')) {
+ int n = s - utmp.ut_host;
+ if (!n)
+ insecure = 0;
+ else
+ if (display_name) {
+ if (!strncmp(utmp.ut_host, display_name, n))
+ insecure = 0;
+#ifdef SOLARIS
+ else
+ if (s = strchr(utmp.ut_host, ' ')) {
+ *s = ':';
+ if (s = strchr(s + 1, ' '))
+ *s = '.';
+ if (!strncmp(utmp.ut_host, display_name, n))
+ insecure = 0;
+ }
+#endif /* SOLARIS */
+ }
+ }
+ }
+#endif /* HAVE_UT_HOST */
+ if (insecure)
+ return (result = 1);
+
+ return (result = 0);
+#else /* NO_INSECURE_CHECK */
+ return 0;
+#endif /* NO_INSECURE_CHECK */
+}
diff --git a/contrib/opie/libopie/keycrunch.c b/contrib/opie/libopie/keycrunch.c
new file mode 100644
index 0000000..7df86d9
--- /dev/null
+++ b/contrib/opie/libopie/keycrunch.c
@@ -0,0 +1,64 @@
+/* keycrunch.c: The opiekeycrunch() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 using the old keycrunch.c as a guide.
+*/
+
+#include "opie_cfg.h"
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include <ctype.h>
+
+#include "opie.h"
+
+int opiekeycrunch FUNCTION((algorithm, result, seed, secret), int algorithm AND char *result AND char *seed AND char *secret)
+{
+ int i, rval = -1;
+ char *c;
+
+ if (!result || !seed || !secret)
+ return 1;
+
+ i = strlen(seed) + strlen(secret);
+ if (!(c = malloc(i + 1)))
+ return -1;
+
+ {
+ char *c2 = c;
+
+ if (algorithm & 0x10)
+ while(*c2 = *(secret++)) c2++;
+
+ while(*seed)
+ if (isspace(*(c2++) = tolower(*(seed++))))
+ goto kcret;
+
+ if (!(algorithm & 0x10))
+ strcpy(c2, secret);
+ }
+
+ opiehashlen(algorithm & 0x0f, c, result, i);
+ rval = 0;
+
+kcret:
+ {
+ char *c2 = c;
+ while(*c2)
+ *(c2++) = 0;
+ }
+
+ free(c);
+ return rval;
+}
diff --git a/contrib/opie/libopie/lock.c b/contrib/opie/libopie/lock.c
new file mode 100644
index 0000000..d6ea56e
--- /dev/null
+++ b/contrib/opie/libopie/lock.c
@@ -0,0 +1,175 @@
+/* lock.c: The opielock() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Do refcounts whether or not we
+ actually lock. Fixed USER_LOCKING=0 case.
+ Modified by cmetz for OPIE 2.22. Added reference count for locks.
+ Changed lock filename/refcount symbol names to better indicate
+ that they're not user serviceable.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Use "principal" instead of "name" to make it clearer.
+ Ifdef around some headers, be more careful about allowed
+ error return values. Check open() return value properly.
+ Avoid NULL.
+ Created at NRL for OPIE 2.2 from opiesubr2.c
+*/
+#include "opie_cfg.h"
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <fcntl.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include "opie.h"
+
+int __opie_lockrefcount = 0;
+
+#if USER_LOCKING
+char *__opie_lockfilename = (char *)0;
+
+/* atexit() handler for opielock() */
+static VOIDRET opieunlockaeh FUNCTION_NOARGS
+{
+ if (__opie_lockfilename) {
+ __opie_lockrefcount = 0;
+ opieunlock();
+ }
+}
+#endif /* USER_LOCKING */
+
+/*
+ Serialize (we hope) authentication of user to prevent race conditions.
+ Creates a lock file with a name of OPIE_LOCK_PREFIX with the user name
+ appended. This file contains the pid of the lock's owner and a time()
+ stamp. We use the former to check for dead owners and the latter to
+ provide an upper bound on the lock duration. If there are any problems,
+ we assume the lock is bogus.
+
+ The value of this locking and its security implications are still not
+ completely clear and require further study.
+
+ One could conceivably hack this facility to provide locking of user
+ accounts after several authentication failures.
+
+ Return -1 on low-level error, 0 if ok, 1 on locking failure.
+*/
+int opielock FUNCTION((principal), char *principal)
+{
+#if USER_LOCKING
+ int fh, waits = 0, rval = -1, pid, t, i;
+ char buffer[128], buffer2[128], *c, *c2;
+
+ if (__opie_lockfilename) {
+ __opie_lockrefcount++;
+ return 0;
+ }
+
+ if (!(__opie_lockfilename = (char *)malloc(sizeof(OPIE_LOCK_PREFIX) + strlen(principal))))
+ return -1;
+
+ strcpy(__opie_lockfilename, OPIE_LOCK_PREFIX);
+ strcat(__opie_lockfilename, principal);
+
+ fh = 0;
+ while (!fh)
+ if ((fh = open(__opie_lockfilename, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) {
+ if ((fh = open(__opie_lockfilename, O_RDWR, 0600)) < 0)
+ goto lockret;
+ if ((i = read(fh, buffer, sizeof(buffer))) <= 0)
+ goto lockret;
+
+ buffer[sizeof(buffer) - 1] = 0;
+ buffer[i - 1] = 0;
+
+ if (!(c = strchr(buffer, '\n')))
+ break;
+
+ *(c++) = 0;
+
+ if (!(c2 = strchr(c, '\n')))
+ break;
+
+ *(c2++) = 0;
+
+ if (!(pid = atoi(buffer)))
+ break;
+
+ if (!(t = atoi(c)))
+ break;
+
+ if ((time(0) + OPIE_LOCK_TIMEOUT) < t)
+ break;
+
+ if (kill(pid, 0))
+ break;
+
+ close(fh);
+ fh = 0;
+ sleep(1);
+ if (waits++ > 3) {
+ rval = 1;
+ goto lockret;
+ };
+ };
+
+ sprintf(buffer, "%d\n%d\n", getpid(), time(0));
+ i = strlen(buffer) + 1;
+ if (lseek(fh, 0, SEEK_SET)) {
+ close(fh);
+ unlink(__opie_lockfilename);
+ fh = 0;
+ goto lockret;
+ };
+ if (write(fh, buffer, i) != i) {
+ close(fh);
+ unlink(__opie_lockfilename);
+ fh = 0;
+ goto lockret;
+ };
+ close(fh);
+ if ((fh = open(__opie_lockfilename, O_RDWR, 0600)) < 0) {
+ unlink(__opie_lockfilename);
+ goto lockret;
+ };
+ if (read(fh, buffer2, i) != i) {
+ close(fh);
+ unlink(__opie_lockfilename);
+ fh = 0;
+ goto lockret;
+ };
+ close(fh);
+ if (memcmp(buffer, buffer2, i)) {
+ unlink(__opie_lockfilename);
+ goto lockret;
+ };
+
+ __opie_lockrefcount++;
+ rval = 0;
+ atexit(opieunlockaeh);
+
+lockret:
+ if (fh)
+ close(fh);
+ return rval;
+#else /* USER_LOCKING */
+ __opie_lockrefcount++;
+ return 0;
+#endif /* USER_LOCKING */
+}
diff --git a/contrib/opie/libopie/login.c b/contrib/opie/libopie/login.c
new file mode 100644
index 0000000..d70280f
--- /dev/null
+++ b/contrib/opie/libopie/login.c
@@ -0,0 +1,130 @@
+/* login.c: The opielogin() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+
+#include "opie_cfg.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <utmp.h>
+
+#if DOUTMPX
+#include <utmpx.h>
+#define pututline(x) pututxline(x)
+#define utmp utmpx
+#endif /* DOUTMPX */
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <sys/stat.h>
+#if DEBUG
+#include <syslog.h>
+#include <errno.h>
+#endif /* DEBUG */
+#include "opie.h"
+
+int opielogin FUNCTION((line, name, host), char *line AND char *name AND char *host)
+{
+ struct utmp u;
+ int rval = 0;
+
+ if (__opiegetutmpentry(line, &u)) {
+#if DEBUG
+ syslog(LOG_DEBUG, "opielogin: __opiegetutmpentry(line=%s, &u) failed", line);
+#endif /* DEBUG */
+ memset(&u, 0, sizeof(struct utmp));
+ if (!strncmp(line, "/dev/", 5))
+ strncpy(u.ut_line, line + 5, sizeof(u.ut_line));
+ else
+ strncpy(u.ut_line, line, sizeof(u.ut_line));
+#if DEBUG
+ syslog(LOG_DEBUG, "opielogin: continuing with ut_line=%s", u.ut_line);
+#endif /* DEBUG */
+ }
+
+#if HAVE_UT_TYPE && defined(USER_PROCESS)
+ u.ut_type = USER_PROCESS;
+#endif /* HAVE_UT_TYPE && defined(USER_PROCESS) */
+#if HAVE_UT_PID
+ u.ut_pid = getpid();
+#endif /* HAVE_UT_PID */
+
+#if HAVE_UT_NAME
+ strncpy(u.ut_name, name, sizeof(u.ut_name));
+ u.ut_name[sizeof(u.ut_name)] = 0;
+#else /* HAVE_UT_NAME */
+#error No ut_name field in struct utmp? (Please send in a bug report)
+#endif /* HAVE_UT_NAME */
+
+#if HAVE_UT_HOST
+ strncpy(u.ut_host, host, sizeof(u.ut_host));
+ u.ut_host[sizeof(u.ut_host)] = 0;
+#endif /* HAVE_UT_HOST */
+
+#if DOUTMPX
+#ifdef HAVE_ONE_ARG_GETTIMEOFDAY
+ gettimeofday(&u->ut_tv);
+#else /* HAVE_ONE_ARG_GETTIMEOFDAY */
+ gettimeofday(&u->ut_tv, NULL);
+#endif /* HAVE_ONE_ARG_GETTIMEOFDAY */
+#else /* DOUTMPX */
+ time(&u.ut_time);
+#endif /* DOUTMPX */
+
+ pututline(&u);
+ endutent();
+
+#if DEBUG
+ syslog(LOG_DEBUG, "opielogin: utmp suceeded");
+#endif /* DEBUG */
+
+dowtmp:
+ {
+ FILE *f;
+
+#if DOUTMPX
+ updutmpx(_PATH_WTMPX, &u);
+#else /* DOUTMPX */
+ if (!(f = __opieopen(_PATH_WTMP, 2, 0664))) {
+ rval = -1;
+#if DEBUG
+ syslog(LOG_DEBUG, "opielogin: wtmp open failed: %s (%d)", strerror(errno), errno);
+#endif /* DEBUG */
+ goto dosetlogin;
+ }
+
+ if (fwrite(&u, sizeof(struct utmp), 1, f) != sizeof(struct utmp)) {
+#if DEBUG
+ syslog(LOG_DEBUG, "opielogin: wtmp write failed: %s (%d)", strerror(errno), errno);
+#endif /* DEBUG */
+ rval = -1;
+ }
+
+ fclose(f);
+#endif /* DOUTMPX */
+ }
+
+#if DEBUG
+ syslog(LOG_DEBUG, "opielogin: wtmp suceeded");
+#endif /* DEBUG */
+
+dosetlogin:
+#if HAVE_SETLOGIN
+ setlogin(name);
+#endif /* HAVE_SETLOGIN */
+
+#if DEBUG
+ syslog(LOG_DEBUG, "opielogin: rval=%d", rval);
+#endif /* DEBUG */
+
+ return rval;
+}
diff --git a/contrib/opie/libopie/lookup.c b/contrib/opie/libopie/lookup.c
new file mode 100644
index 0000000..e3df681
--- /dev/null
+++ b/contrib/opie/libopie/lookup.c
@@ -0,0 +1,30 @@
+/* lookup.c: The opielookup() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 (re-write).
+*/
+
+#include "opie_cfg.h"
+#include <stdio.h>
+#include "opie.h"
+
+int opielookup FUNCTION((opie, principal), struct opie *opie AND char *principal)
+{
+ int i;
+
+ memset(opie, 0, sizeof(struct opie));
+ opie->opie_principal = principal;
+
+ if (i = __opiereadrec(opie))
+ return i;
+
+ return (opie->opie_flags & __OPIE_FLAGS_RW) ? 0 : 2;
+}
+
diff --git a/contrib/opie/libopie/md4c.c b/contrib/opie/libopie/md4c.c
new file mode 100644
index 0000000..fd46857
--- /dev/null
+++ b/contrib/opie/libopie/md4c.c
@@ -0,0 +1,267 @@
+/* md4c.c: "RSA Data Security, Inc. MD4 Message-Digest Algorithm"
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Use the real memcpy() and memset(). Use unified context
+ structure.
+ Modified at NRL for OPIE 2.0.
+ Originally from RSADSI reference code.
+*/
+/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD4 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+/* Constants for MD4Transform routine.
+ */
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static VOIDRET MD4Transform __P((UINT4[4], unsigned char[64]));
+static VOIDRET Encode __P((unsigned char *, UINT4 *, unsigned int));
+static VOIDRET Decode __P((UINT4 *, unsigned char *, unsigned int));
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G and H are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+VOIDRET opiemd4init FUNCTION((context), struct opiemdx_ctx *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD4 block update operation. Continues an MD4 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+VOIDRET opiemd4update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen)
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4) inputLen << 3))
+ < ((UINT4) inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4) inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible. */
+ if (inputLen >= partLen) {
+ memcpy((POINTER) & context->buffer[index], (POINTER) input, partLen);
+ MD4Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD4Transform(context->state, &input[i]);
+
+ index = 0;
+ } else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy((POINTER) & context->buffer[index], (POINTER) & input[i], inputLen - i);
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+VOIDRET opiemd4final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context)
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ Encode(bits, context->count, 8);
+
+ /* Pad out to 56 mod 64. */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ opiemd4update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ opiemd4update(context, bits, 8);
+ /* Store state in digest */
+ Encode(digest, context->state, 16);
+
+ /* Zeroize sensitive information. */
+ memset((POINTER) context, 0, sizeof(*context));
+}
+
+/* MD4 basic transformation. Transforms state based on block.
+ */
+static VOIDRET MD4Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64])
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode(x, block, 64);
+
+ /* Round 1 */
+ FF(a, b, c, d, x[0], S11); /* 1 */
+ FF(d, a, b, c, x[1], S12); /* 2 */
+ FF(c, d, a, b, x[2], S13); /* 3 */
+ FF(b, c, d, a, x[3], S14); /* 4 */
+ FF(a, b, c, d, x[4], S11); /* 5 */
+ FF(d, a, b, c, x[5], S12); /* 6 */
+ FF(c, d, a, b, x[6], S13); /* 7 */
+ FF(b, c, d, a, x[7], S14); /* 8 */
+ FF(a, b, c, d, x[8], S11); /* 9 */
+ FF(d, a, b, c, x[9], S12); /* 10 */
+ FF(c, d, a, b, x[10], S13); /* 11 */
+ FF(b, c, d, a, x[11], S14); /* 12 */
+ FF(a, b, c, d, x[12], S11); /* 13 */
+ FF(d, a, b, c, x[13], S12); /* 14 */
+ FF(c, d, a, b, x[14], S13); /* 15 */
+ FF(b, c, d, a, x[15], S14); /* 16 */
+
+ /* Round 2 */
+ GG(a, b, c, d, x[0], S21); /* 17 */
+ GG(d, a, b, c, x[4], S22); /* 18 */
+ GG(c, d, a, b, x[8], S23); /* 19 */
+ GG(b, c, d, a, x[12], S24); /* 20 */
+ GG(a, b, c, d, x[1], S21); /* 21 */
+ GG(d, a, b, c, x[5], S22); /* 22 */
+ GG(c, d, a, b, x[9], S23); /* 23 */
+ GG(b, c, d, a, x[13], S24); /* 24 */
+ GG(a, b, c, d, x[2], S21); /* 25 */
+ GG(d, a, b, c, x[6], S22); /* 26 */
+ GG(c, d, a, b, x[10], S23); /* 27 */
+ GG(b, c, d, a, x[14], S24); /* 28 */
+ GG(a, b, c, d, x[3], S21); /* 29 */
+ GG(d, a, b, c, x[7], S22); /* 30 */
+ GG(c, d, a, b, x[11], S23); /* 31 */
+ GG(b, c, d, a, x[15], S24); /* 32 */
+
+ /* Round 3 */
+ HH(a, b, c, d, x[0], S31); /* 33 */
+ HH(d, a, b, c, x[8], S32); /* 34 */
+ HH(c, d, a, b, x[4], S33); /* 35 */
+ HH(b, c, d, a, x[12], S34); /* 36 */
+ HH(a, b, c, d, x[2], S31); /* 37 */
+ HH(d, a, b, c, x[10], S32); /* 38 */
+ HH(c, d, a, b, x[6], S33); /* 39 */
+ HH(b, c, d, a, x[14], S34); /* 40 */
+ HH(a, b, c, d, x[1], S31); /* 41 */
+ HH(d, a, b, c, x[9], S32); /* 42 */
+ HH(c, d, a, b, x[5], S33); /* 43 */
+ HH(b, c, d, a, x[13], S34); /* 44 */
+ HH(a, b, c, d, x[3], S31); /* 45 */
+ HH(d, a, b, c, x[11], S32); /* 46 */
+ HH(c, d, a, b, x[7], S33); /* 47 */
+ HH(b, c, d, a, x[15], S34); /* 48 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset((POINTER) x, 0, sizeof(x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static VOIDRET Encode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char) (input[i] & 0xff);
+ output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
+ output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
+ output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+ */
+static VOIDRET Decode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
+ (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
+}
diff --git a/contrib/opie/libopie/md5c.c b/contrib/opie/libopie/md5c.c
new file mode 100644
index 0000000..6b20508
--- /dev/null
+++ b/contrib/opie/libopie/md5c.c
@@ -0,0 +1,304 @@
+/* md5c.c: "RSA Data Security, Inc. MD5 Message-Digest Algorithm"
+ "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm"
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Changed PTR to VOIDPTR.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Don't play macro games with memset/memcpy. Renamed exported
+ functions to avoid conflicts. Use unified context structure.
+ Modified at NRL for OPIE 2.1. Minor autoconf mods.
+ Modified at NRL for OPIE 2.0.
+ Originally from RSADSI reference code.
+*/
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static VOIDRET MD5Transform __P((UINT4[4], unsigned char[64]));
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * Encodes input (UINT4) into output (unsigned char).
+ * Assumes len is a multiple of 4.
+ */
+static VOIDRET EEncode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char) (input[i] & 0xff);
+ output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
+ output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
+ output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
+ }
+}
+
+/*
+ * Decodes input (unsigned char) into output (UINT4).
+ * Assumes len is a multiple of 4.
+ */
+static VOIDRET EDecode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
+ (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
+}
+
+/* F, G, H and I are basic MD5 functions. */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ Rotation is separate from addition to prevent recomputation. */
+
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context. */
+VOIDRET opiemd5init FUNCTION((context), struct opiemdx_ctx *context)
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/*
+ * MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+VOIDRET opiemd5update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen)
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
+ context->count[1]++;
+
+ context->count[1] += ((UINT4) inputLen >> 29);
+ partLen = 64 - index;
+
+ /* Transform as many times as possible. */
+ if (inputLen >= partLen) {
+ memcpy((VOIDPTR)&context->buffer[index], (VOIDPTR)input, partLen);
+ MD5Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform(context->state, &input[i]);
+
+ index = 0;
+ } else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy((VOIDPTR) & context->buffer[index],
+ (VOIDPTR) & input[i],
+ inputLen - i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+VOIDRET opiemd5final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context)
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ EEncode(bits, context->count, 8);
+
+ /* Pad out to 56 mod 64. */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ opiemd5update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ opiemd5update(context, bits, 8);
+
+ /* Store state in digest */
+ EEncode(digest, context->state, 16);
+
+ /* Zeroize sensitive information. */
+ memset((VOIDPTR) context, 0, sizeof(*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+static VOIDRET MD5Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64])
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ EDecode(x, block, 64);
+
+ /* Round 1 */
+ FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset((VOIDPTR)x, 0, sizeof(x));
+}
diff --git a/contrib/opie/libopie/newseed.c b/contrib/opie/libopie/newseed.c
new file mode 100644
index 0000000..af4cac7
--- /dev/null
+++ b/contrib/opie/libopie/newseed.c
@@ -0,0 +1,99 @@
+/* newseed.c: The opienewseed() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.22.
+*/
+
+#include "opie_cfg.h"
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <ctype.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif /* HAVE_SYS_UTSNAME_H */
+#include <errno.h>
+#include "opie.h"
+
+int opienewseed FUNCTION((seed), char *seed)
+{
+ if (!seed)
+ return -1;
+
+ if (seed[0]) {
+ int i;
+
+ if ((i = strlen(seed)) >= OPIE_SEED_MIN) {
+ long j;
+ char *c;
+
+ if (i > OPIE_SEED_MAX)
+ i = OPIE_SEED_MAX;
+
+ c = seed + i - 1;
+
+ while(c != seed) {
+ if (!isdigit(*c))
+ break;
+ c--;
+ }
+
+ c++;
+
+ if (j = strtol(c, (char **)0, 10)) {
+ char buf[OPIE_SEED_MAX];
+
+ *c = 0;
+ strcpy(buf, seed);
+
+ if (errno == ERANGE) {
+ j = 1;
+ } else {
+ int k = 1, l = OPIE_SEED_MAX - strlen(buf);
+ while(l--) k *= 10;
+
+ if (++j >= k)
+ j = 1;
+ }
+
+ sprintf(seed, "%s%04d", buf, j);
+ return 0;
+ }
+ }
+ }
+
+ {
+ {
+ time_t now;
+ time(&now);
+ srand(now);
+ }
+
+ {
+ struct utsname utsname;
+
+ if (uname(&utsname) < 0) {
+#if 0
+ perror("uname");
+#endif /* 0 */
+ utsname.nodename[0] = 'k';
+ utsname.nodename[1] = 'e';
+ }
+ utsname.nodename[2] = 0;
+
+ sprintf(seed, "%s%04d", utsname.nodename, (rand() % 9999) + 1);
+ return 0;
+ }
+ }
+}
+
diff --git a/contrib/opie/libopie/open.c b/contrib/opie/libopie/open.c
new file mode 100644
index 0000000..0082c34
--- /dev/null
+++ b/contrib/opie/libopie/open.c
@@ -0,0 +1,61 @@
+/* open.c: The __opieopen() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "opie.h"
+
+#if !HAVE_LSTAT
+#define lstat(x, y) stat(x, y)
+#endif /* !HAVE_LSTAT */
+
+FILE *__opieopen FUNCTION((file, rw, mode), char *file AND int rw AND int mode)
+{
+ FILE *f;
+ struct stat st;
+
+ if (lstat(file, &st)) {
+ if (errno != ENOENT)
+ return NULL;
+
+ if (!(f = fopen(file, "w")))
+ return NULL;
+
+ fclose(f);
+
+ if (chmod(file, mode))
+ return NULL;
+
+ if (lstat(file, &st))
+ return NULL;
+ }
+
+ if (!S_ISREG(st.st_mode))
+ return NULL;
+
+ {
+ char *fmodes[] = { "r", "r+", "a" };
+
+ if (!(f = fopen(file, fmodes[rw])))
+ return NULL;
+ }
+
+ return f;
+}
diff --git a/contrib/opie/libopie/parsechallenge.c b/contrib/opie/libopie/parsechallenge.c
new file mode 100644
index 0000000..9dca1e6
--- /dev/null
+++ b/contrib/opie/libopie/parsechallenge.c
@@ -0,0 +1,70 @@
+/* parsechallenge.c: The _opieparsechallenge() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 using generator.c as a guide.
+*/
+
+#include "opie_cfg.h"
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include "opie.h"
+
+struct algorithm {
+ char *name;
+ int num;
+};
+
+static struct algorithm algorithms[] = {
+ { "md5", 5 },
+ { "md4", 4 },
+ { "sha1", 3 },
+ { NULL, 0 },
+};
+
+int _opieparsechallenge FUNCTION((buffer, algorithm, sequence, seed), char *buffer AND int *algorithm AND int *sequence AND char **seed)
+{
+ char *c;
+
+ if (!(c = strchr(buffer, ' ')))
+ return 1;
+
+ {
+ struct algorithm *a;
+
+ for (a = algorithms; a->name && strncmp(buffer, a->name, (int)(c - buffer)); a++);
+ if (!a->name)
+ return -1;
+
+ *algorithm = a->num;
+ }
+
+ if ((*sequence = strtoul(++c, &c, 10)) > 9999)
+ return -1;
+
+ while(*c && isspace(*c)) c++;
+ if (!*c)
+ return -1;
+
+ buffer = c;
+ while(*c && !isspace(*c)) c++;
+
+ {
+ int i = (int)(c - buffer);
+
+ if ((i > OPIE_SEED_MAX) || (i < OPIE_SEED_MIN))
+ return -1;
+ }
+
+ *seed = buffer;
+ *c = 0;
+
+ return 0;
+}
diff --git a/contrib/opie/libopie/passcheck.c b/contrib/opie/libopie/passcheck.c
new file mode 100644
index 0000000..3b30d70
--- /dev/null
+++ b/contrib/opie/libopie/passcheck.c
@@ -0,0 +1,50 @@
+/* passcheck.c: The opiepasscheck() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. OPIE_PASS_{MIN,MAX} changed to
+ OPIE_SECRET_{MIN,MAX}.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Created at NRL for OPIE 2.2 from opiesubr.c.
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "opie.h"
+
+/*
+ Applies "good password" rules to the secret pass phrase.
+
+ We currently implement the following:
+
+ Passwords must be at least OPIE_SECRET_MIN (10) characters long.
+ Passwords must be at most OPIE_SECRET_MAX (127) characters long.
+
+ N.B.: Passing NULL pointers to this function is a bad idea.
+*/
+int opiepasscheck FUNCTION((secret), char *secret)
+{
+ int len = strlen(secret);
+
+ if (len < OPIE_SECRET_MIN)
+ return 1;
+
+ if (len > OPIE_SECRET_MAX)
+ return 1;
+
+ return 0;
+}
diff --git a/contrib/opie/libopie/passwd.c b/contrib/opie/libopie/passwd.c
new file mode 100644
index 0000000..e50bf17
--- /dev/null
+++ b/contrib/opie/libopie/passwd.c
@@ -0,0 +1,74 @@
+/* passwd.c: The opiepasswd() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Split most of the function off
+ and turned this into a front-end for the new __opiewriterec().
+ Added code to compute the key from the secret. Use the opie_
+ prefix. Use new opieatob8() and opiebtoa8() return values.
+ Created by cmetz for OPIE 2.22.
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+int opiepasswd FUNCTION((old, mode, principal, n, seed, ks), struct opie *old AND int mode AND char *principal AND int n AND char *seed AND char *ks)
+{
+ int i;
+ struct opie opie;
+
+ if ((mode & 1) && opieinsecure())
+ return -1;
+
+ memset(&opie, 0, sizeof(struct opie));
+
+ if (old) {
+ opie.opie_flags = old->opie_flags;
+ opie.opie_recstart = old->opie_recstart;
+ opie.opie_extrecstart = old->opie_extrecstart;
+ }
+
+ opie.opie_principal = principal;
+ opie.opie_n = n;
+ opie.opie_seed = seed;
+
+ if (ks) {
+ char key[8];
+
+ if (mode & 1) {
+ if (opiekeycrunch(MDX, key, seed, ks))
+ return -1;
+ for (i = n; i; i--)
+ opiehash(key, MDX);
+ if (!(opie.opie_val = opiebtoa8(opie.opie_buf, key)))
+ return -1;
+
+ if (opiekeycrunch(MDX | 0x10, key, seed, ks))
+ return -1;
+
+ if (!(opie.opie_reinitkey = opiebtoa8(opie.opie_extbuf, key)))
+ return -1;
+ } else {
+ if ((opieetob(key, ks) != 1) && !opieatob8(key, ks))
+ return 1;
+ if (!(opie.opie_val = opiebtoa8(opie.opie_buf, key)))
+ return 1;
+ }
+ }
+
+ if (opielock(principal))
+ return -1;
+
+ i = __opiewriterec(&opie);
+
+ if (opieunlock())
+ return -1;
+
+ return i;
+}
diff --git a/contrib/opie/libopie/randomchallenge.c b/contrib/opie/libopie/randomchallenge.c
new file mode 100644
index 0000000..6e0d5b7
--- /dev/null
+++ b/contrib/opie/libopie/randomchallenge.c
@@ -0,0 +1,43 @@
+/* randomchallenge.c: The opierandomchallenge() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Add sha support.
+ Modified by cmetz for OPIE 2.22. Don't include stdio.h.
+ Use opienewseed(). Don't include unneeded headers.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Changed use of gethostname() to uname(). Ifdefed around some
+ headers.
+ Created at NRL for OPIE 2.2 from opiesubr2.c
+*/
+
+#include "opie_cfg.h"
+#include "opie.h"
+
+static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
+
+/* Generate a random challenge */
+/* This could grow into quite a monster, really. Random is good enough for
+ most situations; it is certainly better than a fixed string */
+VOIDRET opierandomchallenge FUNCTION((prompt), char *prompt)
+{
+ char buf[OPIE_SEED_MAX + 1];
+
+ buf[0] = 0;
+ if (opienewseed(buf))
+ strcpy(buf, "ke4452");
+
+ sprintf(prompt, "otp-%s %d %s", algids[MDX], (rand() % 499) + 1, buf);
+}
diff --git a/contrib/opie/libopie/readpass.c b/contrib/opie/libopie/readpass.c
new file mode 100644
index 0000000..4dc22e2
--- /dev/null
+++ b/contrib/opie/libopie/readpass.c
@@ -0,0 +1,304 @@
+/* readpass.c: The opiereadpass() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Use TCSAFLUSH always.
+ Modified by cmetz for OPIE 2.22. Replaced echo w/ flags.
+ Really use FUNCTION.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Flush extraneous characters up to eol. Handle gobs of possible
+ erase and kill keys if on a terminal. To do so, use RAW
+ terminal I/O and handle echo ourselves. (should also help
+ DOS et al portability). Fixed include order. Re-did MSDOS
+ and OS/2 includes. Set up VMIN and VTIME. Added some non-UNIX
+ portability cruft. Limit backspacing and killing. In terminal
+ mode, eat random other control characters. Added eof handling.
+ Created at NRL for OPIE 2.2 from opiesubr.c. Change opiestrip_crlf to
+ opiestripcrlf. Don't strip to seven bits.
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* ANSI C standard library */
+
+#ifdef unix
+#include <fcntl.h> /* POSIX file control function headers */
+#include <termios.h> /* POSIX Terminal I/O functions */
+#if HAVE_UNISTD_H
+#include <unistd.h> /* POSIX standard definitions */
+#endif /* HAVE_UNISTD_H */
+#include <signal.h>
+#include <setjmp.h>
+#endif /* unix */
+
+#ifdef __MSDOS__
+#include <dos.h>
+#endif /* __MSDOS__ */
+
+#ifdef __OS2__
+#define INCL_KBD
+#include <os2.h>
+#include <io.h>
+#endif /* __OS2__ */
+
+#include "opie.h"
+
+#define CONTROL(x) (x - 64)
+
+char *bsseq = "\b \b";
+
+#ifdef unix
+static jmp_buf jmpbuf;
+
+static VOIDRET catch FUNCTION((i), int i)
+{
+ longjmp(jmpbuf, 1);
+}
+#endif /* unix */
+
+char *opiereadpass FUNCTION((buf, len, flags), char *buf AND int len AND int flags)
+{
+#ifdef unix
+ struct termios attr, orig_attr;
+#endif /* unix */
+ char erase[5];
+ char kill[4];
+ char eof[4];
+
+ memset(erase, 0, sizeof(erase));
+ memset(kill, 0, sizeof(kill));
+ memset(eof, 0, sizeof(eof));
+
+ /* This section was heavily rewritten by rja following the model of code
+ samples circa page 151 of the POSIX Programmer's Guide by Donald Lewine,
+ ISBN 0-937175-73-0. That book is Copyright 1991 by O'Reilly &
+ Associates, Inc. All Rights Reserved. I recommend the book to anyone
+ trying to write portable software. rja */
+
+#ifdef unix
+ if (setjmp(jmpbuf))
+ goto error;
+
+ signal(SIGINT, catch);
+#endif /* unix */
+
+ /* Flush any pending output */
+ fflush(stderr);
+ fflush(stdout);
+
+#ifdef unix
+ /* Get original terminal attributes */
+ if (isatty(0)) {
+ if (tcgetattr(0, &orig_attr))
+ return NULL;
+
+ /* copy terminal settings into attr */
+ memcpy(&attr, &orig_attr, sizeof(struct termios));
+
+ attr.c_lflag &= ~(ECHO | ICANON);
+ attr.c_lflag |= ISIG;
+
+ attr.c_cc[VMIN] = 1;
+ attr.c_cc[VTIME] = 0;
+
+ erase[0] = CONTROL('H');
+ erase[1] = 127;
+
+#ifdef CERASE
+ {
+ char *e = erase;
+
+ while(*e)
+ if (*(e++) == CERASE)
+ break;
+
+ if (!*e)
+ *e = CERASE;
+ }
+#endif /* CERASE */
+#ifdef VERASE
+ {
+ char *e = erase;
+
+ while(*e)
+ if (*(e++) == attr.c_cc[VERASE])
+ break;
+
+ if (!*e)
+ *e = attr.c_cc[VERASE];
+ }
+#endif /* VERASE */
+
+ kill[0] = CONTROL('U');
+#ifdef CKILL
+ {
+ char *e = kill;
+
+ while(*e)
+ if (*(e++) == CKILL)
+ break;
+
+ if (!*e)
+ *e = CKILL;
+ }
+#endif /* CKILL */
+#ifdef VKILL
+ {
+ char *e = kill;
+
+ while(*e)
+ if (*(e++) == attr.c_cc[VKILL])
+ break;
+
+ if (!*e)
+ *e = attr.c_cc[VKILL];
+ }
+#endif /* VKILL */
+
+ eof[0] = CONTROL('D');
+#ifdef CEOF
+ {
+ char *e = eof;
+
+ while(*e)
+ if (*(e++) == CEOF)
+ break;
+
+ if (!*e)
+ *e = CEOF;
+ }
+#endif /* CEOF */
+#ifdef VEOF
+ {
+ char *e = eof;
+
+ while(*e)
+ if (*(e++) == attr.c_cc[VEOF])
+ break;
+
+ if (!*e)
+ *e = VEOF;
+ }
+#endif /* VEOF */
+
+ if (tcsetattr(0, TCSAFLUSH, &attr))
+ goto error;
+ }
+#else /* unix */
+ erase[0] = CONTROL('H');
+ erase[1] = 127;
+ kill[0] = CONTROL('U');
+ eof[0] = CONTROL('D');
+ eof[1] = CONTROL('Z');
+#endif /* unix */
+
+ {
+ char *c = buf, *end = buf + len, *e;
+#ifdef __OS2__
+ KBDKEYINFO keyInfo;
+#endif /* __OS2__ */
+
+loop:
+#ifdef unix
+ if (read(0, c, 1) != 1)
+ goto error;
+#endif /* unix */
+#ifdef MSDOS
+ *c = bdos(7, 0, 0);
+#endif /* MSDOS */
+#ifdef __OS2__
+ KbdCharIn(&keyInfo, 0, 0);
+ *c = keyInfo.chChar;
+#endif /* __OS2__ */
+
+ if ((*c == '\r') || (*c == '\n')) {
+ *c = 0;
+ goto restore;
+ }
+
+ e = eof;
+ while(*e)
+ if (*(e++) == *c)
+ goto error;
+
+ e = erase;
+ while(*e)
+ if (*(e++) == *c) {
+ if (c <= buf)
+ goto beep;
+
+ if (flags & 1)
+ write(1, bsseq, sizeof(bsseq) - 1);
+ c--;
+ goto loop;
+ }
+
+ e = kill;
+ while(*e)
+ if (*(e++) == *c) {
+ if (c <= buf)
+ goto beep;
+
+ if (flags & 1)
+ while(c-- > buf)
+ write(1, bsseq, sizeof(bsseq) - 1);
+
+ c = buf;
+ goto loop;
+ }
+
+ if (c < end) {
+ if (*c < 32)
+ goto beep;
+ if (flags & 1)
+ write(1, c, 1);
+ c++;
+ } else {
+ beep:
+ *c = CONTROL('G');
+ write(1, c, 1);
+ }
+
+ goto loop;
+ }
+
+restore:
+#ifdef unix
+ /* Restore previous tty modes */
+ if (isatty(0))
+ if (tcsetattr(0, TCSAFLUSH, &orig_attr))
+ return NULL;
+
+ signal(SIGINT, SIG_DFL);
+#endif /* unix */
+
+ /* After the secret key is taken from the keyboard, the line feed is
+ written to standard error instead of standard output. That means that
+ anyone using the program from a terminal won't notice, but capturing
+ standard output will get the key words without a newline in front of
+ them. */
+ if (!(flags & 4)) {
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+
+ return buf;
+
+error:
+ *buf = 0;
+ buf = NULL;
+ goto restore;
+}
diff --git a/contrib/opie/libopie/readrec.c b/contrib/opie/libopie/readrec.c
new file mode 100644
index 0000000..c98daaa
--- /dev/null
+++ b/contrib/opie/libopie/readrec.c
@@ -0,0 +1,218 @@
+/* readrec.c: The __opiereadrec() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3.
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
+#include <ctype.h>
+#include <errno.h>
+#if DEBUG
+#include <syslog.h>
+#endif /* DEBUG */
+#include "opie.h"
+
+static int parserec FUNCTION((opie), struct opie *opie)
+{
+ char *c, *c2;
+
+ if (!(c2 = strchr(opie->opie_principal = opie->opie_buf, ' ')))
+ return -1;
+
+ while(*c2 == ' ') c2++;
+ *(c2 - 1) = 0;
+
+ if (!(c2 = strchr(c = c2, ' ')))
+ return -1;
+
+ *(c2++) = 0;
+
+ if (!(opie->opie_n = atoi(c)))
+ return -1;
+
+ if (!(c2 = strchr(opie->opie_seed = c2, ' ')))
+ return -1;
+
+ *(c2++) = 0;
+
+ while(*c2 == ' ') c2++;
+
+ if (!(c2 = strchr(opie->opie_val = c2, ' ')))
+ return -1;
+
+ *(c2++) = 0;
+
+ return 0;
+}
+
+static int parseextrec FUNCTION((opie), struct opie *opie)
+{
+ char *c;
+
+ if (!(c = strchr(opie->opie_extbuf, ' ')))
+ return -1;
+
+ *(c++) = 0;
+ while(*c == ' ') c++;
+
+ if (!(c = strchr(opie->opie_reinitkey = c, ' ')))
+ return -1;
+
+ *(c++) = 0;
+
+ return 0;
+}
+
+int __opiereadrec FUNCTION((opie), struct opie *opie)
+{
+ FILE *f = NULL, *f2 = NULL;
+ int rval = -1;
+
+ if (!(f = __opieopen(STD_KEY_FILE, 0, 0644))) {
+#if DEBUG
+ syslog(LOG_DEBUG, "__opiereadrec: __opieopen(STD_KEY_FILE..) failed!");
+#endif /* DEBUG */
+ goto ret;
+ }
+
+ if (!(f2 = __opieopen(EXT_KEY_FILE, 0, 0600))) {
+#if DEBUG
+ syslog(LOG_DEBUG, "__opiereadrec: __opieopen(EXT_KEY_FILE..) failed!");
+#endif /* DEBUG */
+ }
+
+ {
+ int i;
+
+ if ((i = open(STD_KEY_FILE, O_RDWR)) < 0) {
+ opie->opie_flags &= ~__OPIE_FLAGS_RW;
+#if DEBUG
+ syslog(LOG_DEBUG, "__opiereadrec: open(STD_KEY_FILE, O_RDWR) failed: %s", strerror(errno));
+#endif /* DEBUG */
+ } else {
+ close(i);
+ if ((i = open(EXT_KEY_FILE, O_RDWR)) < 0) {
+ opie->opie_flags &= ~__OPIE_FLAGS_RW;
+#if DEBUG
+ syslog(LOG_DEBUG, "__opiereadrec: open(STD_KEY_FILE, O_RDWR) failed: %s", strerror(errno));
+#endif /* DEBUG */
+ } else {
+ close(i);
+ opie->opie_flags |= __OPIE_FLAGS_RW;
+ }
+ }
+ }
+
+ if (opie->opie_buf[0]) {
+ if (fseek(f, opie->opie_recstart, SEEK_SET))
+ goto ret;
+
+ if (fgets(opie->opie_buf, sizeof(opie->opie_buf), f))
+ goto ret;
+
+ if (parserec(opie))
+ goto ret;
+
+ if (opie->opie_extbuf[0]) {
+ if (!f2) {
+#if DEBUG
+ syslog(LOG_DEBUG, "__opiereadrec: can't read ext file, but could before?");
+#endif /* DEBUG */
+ goto ret;
+ }
+
+ if (fseek(f2, opie->opie_extrecstart, SEEK_SET))
+ goto ret;
+
+ if (fgets(opie->opie_extbuf, sizeof(opie->opie_extbuf), f2))
+ goto ret;
+
+ if (parseextrec(opie))
+ goto ret;
+ }
+
+ rval = 0;
+ goto ret;
+ }
+
+ if (!opie->opie_principal)
+ return -1;
+
+ {
+ char *c, principal[OPIE_PRINCIPAL_MAX];
+ int i;
+
+ if (c = strchr(opie->opie_principal, ':'))
+ *c = 0;
+ if (strlen(opie->opie_principal) > OPIE_PRINCIPAL_MAX)
+ (opie->opie_principal)[OPIE_PRINCIPAL_MAX] = 0;
+
+ strcpy(principal, opie->opie_principal);
+
+ do {
+ if ((opie->opie_recstart = ftell(f)) < 0)
+ goto ret;
+
+ if (!fgets(opie->opie_buf, sizeof(opie->opie_buf), f)) {
+ rval = 1;
+ goto ret;
+ }
+
+ if (parserec(opie))
+ goto ret;
+ } while (strcmp(principal, opie->opie_principal));
+
+ if (!f2) {
+ opie->opie_extbuf[0] = rval = 0;
+ goto ret;
+ }
+
+ do {
+ if ((opie->opie_extrecstart = ftell(f2)) < 0)
+ goto ret;
+
+ if (!fgets(opie->opie_extbuf, sizeof(opie->opie_extbuf), f2)) {
+ if (feof(f2)) {
+ opie->opie_reinitkey = NULL;
+ rval = 0;
+ } else
+ rval = 1;
+ goto ret;
+ }
+
+ if (parseextrec(opie))
+ goto ret;
+ } while (strcmp(principal, opie->opie_extbuf));
+
+ rval = 0;
+ }
+
+ret:
+ if (f)
+ fclose(f);
+ if (f2)
+ fclose(f2);
+ return rval;
+}
+
diff --git a/contrib/opie/libopie/unlock.c b/contrib/opie/libopie/unlock.c
new file mode 100644
index 0000000..35c266d
--- /dev/null
+++ b/contrib/opie/libopie/unlock.c
@@ -0,0 +1,103 @@
+/* unlock.c: The opieunlock() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Do refcounts whether or not
+ we actually lock. Fixed USER_LOCKING=0 case.
+ Modified by cmetz for OPIE 2.22. Added reference count support.
+ Changed lock filename/refcount symbol names to better indicate
+ that they're not user serviceable.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration.
+ Check for read() == -1. ifdef around unistd.h.
+ Created at NRL for OPIE 2.2 from opiesubr2.c
+*/
+#include "opie_cfg.h"
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <fcntl.h>
+#include "opie.h"
+
+extern int __opie_lockrefcount;
+#if USER_LOCKING
+extern char *__opie_lockfilename;
+#endif /* USER_LOCKING */
+
+/*
+ Just remove the lock, right?
+ Well, not exactly -- we need to make sure it's ours.
+*/
+int opieunlock FUNCTION_NOARGS
+{
+#if USER_LOCKING
+ int fh, rval = -1, pid, t, i;
+ char buffer[128], *c, *c2;
+
+ if (--__opie_lockrefcount > 0)
+ return 0;
+
+ if (!__opie_lockfilename)
+ return -1;
+
+ if (!(fh = open(__opie_lockfilename, O_RDWR, 0600)))
+ goto unlockret;
+
+ if ((i = read(fh, buffer, sizeof(buffer))) < 0)
+ goto unlockret;
+
+ buffer[sizeof(buffer) - 1] = 0;
+ buffer[i - 1] = 0;
+
+ if (!(c = strchr(buffer, '\n')))
+ goto unlockret;
+
+ *(c++) = 0;
+
+ if (!(c2 = strchr(c, '\n')))
+ goto unlockret;
+
+ *(c2++) = 0;
+
+ if (!(pid = atoi(buffer)))
+ goto unlockret;
+
+ if (!(t = atoi(c)))
+ goto unlockret;
+
+ if ((pid != getpid()) && (time(NULL) + OPIE_LOCK_TIMEOUT <= t) &&
+ (!kill(pid, 0))) {
+ rval = 1;
+ goto unlockret1;
+ }
+
+ rval = 0;
+
+unlockret:
+ unlink(__opie_lockfilename);
+
+unlockret1:
+ if (fh)
+ close(fh);
+ free(__opie_lockfilename);
+ __opie_lockfilename = NULL;
+ return rval;
+#else /* USER_LOCKING */
+ if (__opie_lockrefcount-- > 0)
+ return 0;
+
+ return -1;
+#endif /* USER_LOCKING */
+}
diff --git a/contrib/opie/libopie/verify.c b/contrib/opie/libopie/verify.c
new file mode 100644
index 0000000..7388a8a
--- /dev/null
+++ b/contrib/opie/libopie/verify.c
@@ -0,0 +1,255 @@
+/* verify.c: The opieverify() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 using the old verify.c as a guide.
+*/
+
+#include "opie_cfg.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include "opie.h"
+
+#define RESPONSE_STANDARD 0
+#define RESPONSE_WORD 1
+#define RESPONSE_HEX 2
+#define RESPONSE_INIT 3
+#define RESPONSE_INIT_WORD 4
+#define RESPONSE_UNKNOWN 5
+
+struct _rtrans {
+ int type;
+ char *name;
+};
+
+static struct _rtrans rtrans[] = {
+ { RESPONSE_WORD, "word" },
+ { RESPONSE_HEX, "hex" },
+ { RESPONSE_INIT, "init" },
+ { RESPONSE_INIT_WORD, "init-word" },
+ { RESPONSE_STANDARD, "" },
+ { RESPONSE_UNKNOWN, NULL }
+};
+
+static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
+
+static int changed FUNCTION((opie), struct opie *opie)
+{
+ struct opie opie2;
+
+ memset(&opie2, 0, sizeof(struct opie));
+ opie2.opie_principal = opie->opie_principal;
+ if (__opiereadrec(&opie2))
+ return 1;
+
+ if ((opie2.opie_n != opie->opie_n) || strcmp(opie2.opie_val, opie->opie_val) || strcmp(opie2.opie_seed, opie->opie_seed))
+ return 1;
+
+ memset(&opie2, 0, sizeof(struct opie));
+ return 0;
+}
+
+int opieverify FUNCTION((opie, response), struct opie *opie AND char *response)
+{
+ int i, rval = -1;
+ char *c;
+ char key[8], fkey[8], lastkey[8];
+ struct opie nopie;
+
+ if (!opie || !response)
+ goto verret;
+
+ if (!opie->opie_principal)
+#if DEBUG
+ abort();
+#else /* DEBUG */
+ goto verret;
+#endif /* DEBUG */
+
+ if (!opieatob8(lastkey, opie->opie_val))
+ goto verret;
+
+ if (c = strchr(response, ':')) {
+ *(c++) = 0;
+ {
+ struct _rtrans *r;
+ for (r = rtrans; r->name && strcmp(r->name, response); r++);
+ i = r->type;
+ }
+ } else
+ i = RESPONSE_STANDARD;
+
+ switch(i) {
+ case RESPONSE_STANDARD:
+ i = 1;
+
+ if (opieetob(key, response) == 1) {
+ memcpy(fkey, key, sizeof(key));
+ opiehash(fkey, MDX);
+ i = memcmp(fkey, lastkey, sizeof(key));
+ }
+ if (i && opieatob8(key, response)) {
+ memcpy(fkey, key, sizeof(key));
+ opiehash(fkey, MDX);
+ i = memcmp(fkey, lastkey, sizeof(key));
+ }
+ break;
+ case RESPONSE_WORD:
+ i = 1;
+
+ if (opieetob(key, c) == 1) {
+ memcpy(fkey, key, sizeof(key));
+ opiehash(fkey, MDX);
+ i = memcmp(fkey, lastkey, sizeof(key));
+ }
+ break;
+ case RESPONSE_HEX:
+ i = 1;
+
+ if (opieatob8(key, c)) {
+ memcpy(fkey, key, sizeof(key));
+ opiehash(fkey, MDX);
+ i = memcmp(fkey, lastkey, sizeof(key));
+ }
+ break;
+ case RESPONSE_INIT:
+ case RESPONSE_INIT_WORD:
+ {
+ char *c2;
+ char newkey[8], ckxor[8], ck[8], cv[8], cvc[8];
+ char buf[OPIE_SEED_MAX + 48 + 1];
+
+ if (!(c2 = strchr(c, ':')))
+ goto verret;
+
+ *(c2++) = 0;
+
+ if (i == RESPONSE_INIT) {
+ if (!opieatob8(key, c))
+ goto verret;
+ } else {
+ if (opieetob(key, c) != 1)
+ goto verret;
+ }
+
+ memcpy(fkey, key, sizeof(key));
+ opiehash(fkey, MDX);
+
+ if (memcmp(fkey, lastkey, sizeof(key)))
+ goto verret;
+
+ if (changed(opie))
+ goto verret;
+
+ opie->opie_n--;
+
+ if (!opiebtoa8(opie->opie_val, key))
+ goto verret;
+
+ if (__opiewriterec(opie))
+ goto verret;
+
+ if (!(c2 = strchr(c = c2, ':')))
+ goto verret;
+
+ *(c2++) = 0;
+
+ {
+ int j;
+
+ if (_opieparsechallenge(c, &j, &(opie->opie_n), &(opie->opie_seed)) || (j != MDX))
+ goto verret;
+ }
+
+ if (!(c2 = strchr(c = c2, ':')))
+ goto verret;
+
+ *(c2++) = 0;
+
+ if (i == RESPONSE_INIT) {
+ if (!opieatob8(newkey, c))
+ goto verret;
+ } else {
+ if (opieetob(newkey, c) != 1)
+ goto verret;
+ }
+
+ if (!opie->opie_reinitkey || (opie->opie_reinitkey[0] == '*'))
+ goto verwrt;
+
+ if (!(c2 = strchr(c = c2, ':')))
+ goto verret;
+
+ *(c2++) = 0;
+
+ if (i == RESPONSE_INIT) {
+ if (!opieatob8(ckxor, c))
+ goto verret;
+ if (!opieatob8(cv, c2))
+ goto verret;
+ } else {
+ if (opieetob(ckxor, c) != 1)
+ goto verret;
+ if (opieetob(cv, c2) != 1)
+ goto verret;
+ }
+
+ if (!opieatob8(ck, opie->opie_reinitkey))
+ goto verret;
+
+ c = buf;
+ memcpy(c, ck, sizeof(ck)); c += sizeof(ck);
+ memcpy(c, key, sizeof(key)); c += sizeof(key);
+ c += sprintf(c, "%s 499 %s", algids[MDX], opie->opie_seed);
+ memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey);
+ memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor);
+ memcpy(c, ck, sizeof(ck)); c += sizeof(ck);
+ opiehashlen(MDX, buf, cvc, (unsigned int)c - (unsigned int)buf);
+
+ if (memcmp(cv, cvc, sizeof(cv)))
+ goto verret;
+
+ for (i = 0; i < 8; i++)
+ ck[i] ^= ckxor[i];
+
+ if (!opiebtoa8(opie->opie_reinitkey, ck))
+ goto verret;
+
+ memcpy(key, newkey, sizeof(key));
+ }
+ goto verwrt;
+ case RESPONSE_UNKNOWN:
+ rval = 1;
+ goto verret;
+ default:
+ rval = -1;
+ goto verret;
+ }
+
+ if (i) {
+ rval = 1;
+ goto verret;
+ }
+
+ if (changed(opie))
+ goto verret;
+
+ opie->opie_n--;
+
+verwrt:
+ if (!opiebtoa8(opie->opie_val, key))
+ goto verret;
+ rval = __opiewriterec(opie);
+
+verret:
+ opieunlock();
+ memset(opie, 0, sizeof(struct opie));
+ return rval;
+}
diff --git a/contrib/opie/libopie/version.c b/contrib/opie/libopie/version.c
new file mode 100644
index 0000000..48b1dc5
--- /dev/null
+++ b/contrib/opie/libopie/version.c
@@ -0,0 +1,27 @@
+/* version.c: The opieversion() library function.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Created at NRL for OPIE 2.2 from opiesubr.c.
+*/
+#include "opie_cfg.h"
+#include "opie.h"
+
+VOIDRET opieversion FUNCTION_NOARGS
+{
+ printf("\nOPIE %s (%s)\n\n", VERSION, DATE);
+ exit(0);
+}
diff --git a/contrib/opie/libopie/writerec.c b/contrib/opie/libopie/writerec.c
new file mode 100644
index 0000000..6978669
--- /dev/null
+++ b/contrib/opie/libopie/writerec.c
@@ -0,0 +1,85 @@
+/* writerec.c: The __opiewriterec() library function.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 from passwd.c.
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#if TM_IN_SYS_TIME
+#include <sys/time.h>
+#else /* TM_IN_SYS_TIME */
+#include <time.h>
+#endif /* TM_IN_SYS_TIME */
+#include <sys/types.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include "opie.h"
+
+char *__opienone = "****************";
+
+int __opiewriterec FUNCTION((opie), struct opie *opie)
+{
+ char buf[17], buf2[64];
+ time_t now;
+ FILE *f, *f2 = NULL;
+ int i = 0;
+
+ time(&now);
+ if (strftime(buf2, sizeof(buf2), " %b %d,%Y %T", localtime(&now)) < 1)
+ return -1;
+
+ if (!(opie->opie_flags & __OPIE_FLAGS_READ)) {
+ struct opie opie2;
+ i = opielookup(&opie2, opie->opie_principal);
+ }
+
+ switch(i) {
+ case 0:
+ if (!(f = __opieopen(STD_KEY_FILE, 1, 0644)))
+ return -1;
+ if (!(f2 = __opieopen(EXT_KEY_FILE, 1, 0600)))
+ return -1;
+ if (fseek(f, opie->opie_recstart, SEEK_SET))
+ return -1;
+ if (fseek(f2, opie->opie_extrecstart, SEEK_SET))
+ return -1;
+ break;
+ case 1:
+ if (!(f = __opieopen(STD_KEY_FILE, 2, 0644)))
+ return -1;
+ if (!(f2 = __opieopen(EXT_KEY_FILE, 2, 0600)))
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+
+ if (fprintf(f, "%s %04d %-16s %s %-21s\n", opie->opie_principal, opie->opie_n, opie->opie_seed, opie->opie_val ? opie->opie_val : __opienone, buf2) < 1)
+ return -1;
+
+ fclose(f);
+
+ if (f2) {
+ if (fprintf(f2, "%-32s %-16s %-77s\n", opie->opie_principal, opie->opie_reinitkey ? opie->opie_reinitkey : __opienone, "") < 1)
+ return -1;
+
+ fclose(f2);
+ }
+
+ return 0;
+}
diff --git a/contrib/opie/logwtmp.c b/contrib/opie/logwtmp.c
new file mode 100644
index 0000000..4d9dcbf
--- /dev/null
+++ b/contrib/opie/logwtmp.c
@@ -0,0 +1,154 @@
+/* logwtmp.c: Put an entry in the wtmp file.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.22. Call gettimeofday() properly.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Ifdef around some headers. Added file close hook.
+ Modified at NRL for OPIE 2.1. Set process type for HPUX.
+ Modified at NRL for OPIE 2.0.
+ Originally from BSD.
+*/
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 "opie_cfg.h"
+
+#include <sys/types.h>
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <utmp.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+
+#include "opie.h"
+
+static int fd = -1;
+
+#if DOUTMPX
+static int fdx = -1;
+#include <utmpx.h>
+#endif /* DOUTMPX */
+
+#ifndef _PATH_WTMP
+#define _PATH_WTMP "/usr/adm/wtmp"
+#endif
+
+#ifndef _PATH_WTMPX
+#define _PATH_WTMPX "/usr/adm/wtmpx"
+#endif /* _PATH_UTMPX */
+
+/*
+ * Modified version of logwtmp that holds wtmp file open
+ * after first call, for use with ftp (which may chroot
+ * after login, but before logout).
+ */
+VOIDRET logwtmp FUNCTION((line, name, host), char *line AND char *name AND char *host)
+{
+ struct utmp ut;
+
+#if DOUTMPX
+ struct utmpx utx;
+#endif /* DOUTMPX */
+ struct stat buf;
+
+ memset(&ut, 0, sizeof(struct utmp));
+
+ if (!line) {
+ close(fd);
+#if DOUTMPX
+ close(fdx);
+#endif /* DOUTMPX */
+ }
+
+ if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY | O_APPEND, 0)) < 0)
+ return;
+ if (fstat(fd, &buf) == 0) {
+#if HAVE_UT_TYPE && defined(USER_PROCESS)
+ ut.ut_type = USER_PROCESS;
+#endif /* HAVE_UT_TYPE && defined(USER_PROCESS) */
+#if HAVE_UT_PID
+ ut.ut_pid = getpid();
+#endif /* HAVE_UT_PID */
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+#if !DOUTMPX
+ strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+#endif /* !DOUTMPX */
+ time(&ut.ut_time);
+ if (write(fd, (char *) &ut, sizeof(struct utmp)) !=
+ sizeof(struct utmp))
+ ftruncate(fd, buf.st_size);
+ }
+#if DOUTMPX
+ memset(&utx, 0, sizeof(struct utmpx));
+
+ if (fdx < 0 && (fdx = open(WTMPX_FILE, O_WRONLY | O_APPEND, 0)) < 0)
+ return;
+ if (fstat(fdx, &buf) == 0) {
+ strncpy(utx.ut_line, line, sizeof(utx.ut_line));
+ strncpy(utx.ut_name, name, sizeof(utx.ut_name));
+ strncpy(utx.ut_host, host, sizeof(utx.ut_host));
+#if HAVE_GETTIMEOFDAY
+#if HAVE_ONE_ARG_GETTIMEOFDAY
+ gettimeofday(&utx.ut_tv);
+#else /* HAVE_ONE_ARG_GETTIMEOFDAY */
+ gettimeofday(&utx.ut_tv, NULL);
+#endif /* HAVE_ONE_ARG_GETTIMEOFDAY */
+#endif /* HAVE_GETTIMEOFDAY */
+ if (write(fdx, (char *) &utx, sizeof(struct utmpx)) !=
+ sizeof(struct utmpx))
+ ftruncate(fdx, buf.st_size);
+ }
+#endif /* DOUTMPX */
+}
diff --git a/contrib/opie/opie.4 b/contrib/opie/opie.4
new file mode 100644
index 0000000..97eb73d
--- /dev/null
+++ b/contrib/opie/opie.4
@@ -0,0 +1,346 @@
+.\" opie.4: Overview of the OPIE software.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. Removed
+.\" references to the old square brackets challenge delimiters.
+.\" Modified at NRL for OPIE 2.01. Updated UNIX trademark credit.
+.\" Definition of "seed" written by Neil Haller of Bellcore
+.\" Written at NRL for OPIE 2.0.
+.\"
+.TH OPIE 4 "January 10, 1995"
+.SH NAME
+.B OPIE \- One-time Passwords In Everything
+.SH DESCRIPTION
+.LP
+OPIE is a package derived from the Bellcore S/Key Version 1 distribution
+that helps to secure a system against replay attacks (see below). It does so
+using a secure hash function and a challenge/response system. It provides
+replacements for the
+.IR login (1),
+.IR su (1),
+and
+.IR ftpd (8)
+programs that use OPIE
+authentication as well as demonstrate how a program might be adapted to use
+OPIE authentication. OPIE was developed at and for the United States Naval
+Research Laboratory (NRL). OPIE is derived in part from Berkeley Standard
+Distribution UNIX and the Bellcore S/Key Version 1 distribution.
+.LP
+From the average user's perspective, OPIE is a nuisance that prevents their
+account from being broken into. The first time a user wishes to use OPIE,
+(s)he needs to use the
+.IR opiepasswd (1)
+command to put an entry for them into
+the OPIE database. The user can then use OPIE to authenticate themselves
+with any program that supports it. If no other clients are being used,
+this means they can use OPIE to
+.I telnet,
+.I rlogin,
+or
+.I ftp
+into the system,
+log in on a terminal port (like a modem), or switch to another user's
+account. When they would normally be asked for a password, they will get
+a challenge from the server. They then need to copy that challenge (or
+re-type, if they don't have the ability to copy and paste through something
+like a window system) to their calculator program, enter their password,
+then copy (or re-type) the response from the calculator as their password.
+While this will seem cumbersome at first, with some practice, it becomes
+easy.
+
+.SH TERMS
+.TP
+.I user name
+The name that the system knows you as. For example, "jdoe".
+.TP
+.I secret password
+A password, usually selected by the user, that is needed to gain access to the
+system. For example, "SEc1_rt".
+.TP
+.I challenge
+A packet of information output by a system when it wishes to authenticate a
+user. In OPIE, this is a three-item group consisting of a hash identifier,
+a sequence number, and a seed. This
+information is needed by the OPIE calculator to generate a proper response.
+For example, "otp-md5 95 wi14321".
+.TP
+.I response
+A packet of information generated from a challenge that is used by a system to
+authenticate a user. In OPIE, this is a group of six words that is generated by
+the calculator given the challenge and the secret password. For example,
+"PUP SOFT ROSE BIAS FLAG END".
+.TP
+.I seed
+A piece of information that is used in conjunction with the secret password
+and sequence numer to compute the response. Its purpose is to allow the same
+secret password to be used for multiple sequences, by changing the seed, or
+for authentication to multiple machines by using different seeds.
+.TP
+.I sequence number
+A counter used to keep track of key iterations. In OPIE, each time a successful
+response is received by the system, the sequence number is decremented. For
+example, "95".
+.TP
+.I hash identifier
+A piece of text that identifies the actual algorithm that needs to be used to
+generate a proper response. In OPIE, the only two valid hash identifiers are
+"otp-md4", which selects MD4 hashing, and "otp-md5", which selects MD5.
+
+.SH REPLAY ATTACKS
+When you use a network terminal program like
+.IR telnet (1)
+or even use a modem to log into a
+computer system, you need a user name and a secret password. Anyone who can
+provide those to the system is recognized as you because, in theory, only you
+would have your secret password. Unfortunately, it is now easy to listen in
+on many computer communications media. From modem communication to many
+networks, your password is not usually safe over remote links. If a
+cracker can listen in when you send your password, (s)he then has a copy
+of your password that can be used at any time in the future to access your
+account. On more than one occasion, major sites on the Internet have been
+broken into exactly this way.
+.LP
+All an attacker has to
+do is capture your password once and then replay it to the server when it's
+asked for. Even if the password is communicated between machines in encoded
+or encrypted form, as long as a cracker can get in by simply replaying
+a previously captured communication, you are at risk. Up until very recently,
+Novell NetWare was vulnerable this way. A cracker couldn't find out what your
+password actually is, but (s)he didn't need to -- all that was necessary to
+get into your account was to capture the encrypted password and send that
+back to the server when asked for it.
+
+.SH ONE-TIME PASSWORDS
+One solution to the problem of replay attacks
+is to keep changing the way that a password is being encoded so that what is
+sent over the link to another system can only be used once. If you can do that,
+then a cracker can replay it as many times as (s)he wants -- it's just not
+going to get them anywhere. It's important, however, to make sure you encode
+the password in such a way that the cracker can't use the encoded version to
+figure out what the password is or what a future encoded password will be.
+Otherwise, while still an improvement over no encoding or a fixed encoding,
+you can still be broken into.
+
+.SH THE S/KEY ALGORITHM
+
+A solution to this whole problem was invented by Lamport in 1981. This
+technique was implemented by Haller, Karn, and Walden at Bellcore. They
+They created a free software package called "S/Key" that used an algorithm
+called a cryptographic checksum. A cryptographic checksum is a strong one-way
+function such that, knowing the result of such a function, an attacker still
+cannot feasably determine the input. Further, unlike cyclic redundancy
+checksums (CRCs), cryptographic checksums have few inputs that result in the
+same output.
+.LP
+In S/Key, what changes is the number of
+times the password is run through the secure hash. The password is run through
+the secure hash once, then the output of the hash is run through the secure
+hash again, that output is run through the secure hash again, and so on until
+the number of times the password has been run through the secure hash is equal
+to the desired sequence number. This is much slower than just, say, putting
+the sequence number in before the password and running that through the secure
+hash once, but it gains you one significant benefit. The server machine you
+are trying to connect to has to have some way to determine whether the output
+of that whole mess is right. If it stores it either without any encoding or
+with a normal encoding, a cracker could still get at your password. But if it
+stores it with a secure hash, then how does it account for the response
+changing every time because the sequence number is changing? Also what if you
+can never get to the machine any way that can't be listened in on? How do you
+change your password without sending it over the link?
+.LP
+The clever solution
+devised by Lamport is to keep in mind that the sequence number is
+always decrementing by one and that, in the S/Key system, simply by running any
+response with a sequence number N through the secure hash, you can get the
+response with a sequence number N+1, but you can't go the other way. At any
+given time, call the sequence number of the last valid response that the
+system got N+1 and the sequence number of the response you are giving it N.
+If the password that generated the response for N is the same as the one for
+N+1, then you should be able to run the response for N through the secure hash
+one more time, for a total of N+1 times, and get the same response as you got
+back for N+1. Once you compare the two and find that they are the same, you
+subtract one from N so that, now, the key for N that you just verified becomes
+the new key for N+1 that you can store away to use the next time you need to
+verify a key. This also means that if you need to change your password but
+don't have a secure way to access your machine, all the system really needs to
+have to verify your password is a valid response for one more than the sequence
+number you want to start with.
+.LP
+Just for good measure, each side of
+all of this uses a seed in conjunction with your password when it actually
+generates and verifies the responses. This helps to jumble things up a little
+bit more, just in case. Otherwise, someone with a lot of time and disk space
+on their hands could generate all the responses for a lot of frequent passwords
+and defeat the system.
+.LP
+This is not, by any means, the best explanation of how the S/Key algorithm
+works or some of the more minor details. For that, you should go to some of
+the papers now published on the topic. It is simply a quick-and-dirty
+introduction to what's going on under the hood.
+
+.SH OPIE COMPONENTS
+
+Included in the OPIE distribution are three OPIE client programs:
+.IR opielogin (1),
+.IR opiesu (1),
+and
+.IR opieftpd (8).
+These three programs are modified versions of the
+freely available 4.3BSD Net/2 versions of
+.IR login (1),
+.IR su (1),
+and
+.IR ftpd (8),
+respectively. Although most of the modifications actually done to them are so
+that they will work on as many machines as possible, they also have been
+modified to support OPIE for authentication. As you will see from the source,
+it is not very difficult to add support for OPIE to other programs.
+.LP
+There are also three programs in the OPIE distribution that are specific to
+the OPIE system:
+.IR opiepasswd (1),
+which allows a user to set and change their
+OPIE password,
+.IR opieinfo (1),
+which allows a user to find out what their current
+sequence number and seed are, and
+.IR opiekey(1),
+which is an OPIE key calculator.
+
+.LP ADDING OPIE TO OTHER PROGRAMS
+
+Adding OPIE authentication to programs other than the ones included as clients
+in the OPIE distribution isn't very difficult. First, you will need to make
+sure that the program includes <stdio.h> somewhere. Then, below the other
+includes such as <stdio.h>, but before variable declarations, you need to
+include "opie.h". You need to add a variable of type "struct opie" to your
+program, you need to make sure that the buffer that you use to get a password
+from the user is big enough to hold OPIE_RESPONSE_MAX+1 characters, and you
+need to have a buffer in which to store the challenge string that is big enough
+to hold OPIE_PROMPT_MAX+1 characters.
+.LP
+When you are ready to output the challenge string and know the user's name,
+you would use a call to opiechallenge. Later, to verify the response received,
+you would use a call to opieverify. For example:
+.sp 0
+
+.sp 0
+ #include <stdio.h>
+.sp 0
+ .
+.sp 0
+ .
+.sp 0
+ #include "opie.h"
+.sp 0
+ .
+.sp 0
+ .
+.sp 0
+ char *user_name;
+.sp 0
+ /* Always remember the trailing null! */
+.sp 0
+ char password[OPIE_RESPONSE_MAX+1];
+.sp 0
+ .
+.sp 0
+ .
+.sp 0
+ struct opie opiedata;
+.sp 0
+ char opieprompt[OPIE_PROMPT_MAX+1];
+.sp 0
+ .
+.sp 0
+ .
+.sp 0
+ opiechallenge(&opiedata, user_name, &opieprompt);
+.sp 0
+ .
+.sp 0
+ .
+.sp 0
+ if (opieverify(&opiedata, password)) {
+.sp 0
+ printf("Login incorrect");
+.sp 0
+.SH TERMINAL SECURITY AND OPIE
+
+When using OPIE, you need to be careful not to allow your password to be
+communicated over an insecure channel where someone might be able to listen
+in and capture it. OPIE can protect you against people who might get your
+password from snooping on the line, but only if you make sure that the password
+itself never gets sent over the line. The important thing is to always run the
+OPIE calculator on whichever machine you are actually using - never on a machine
+you are connected to by network or by dialup.
+.LP
+You need to be careful about the
+X Window System, because it changes things quite a bit. For instance, if you
+run an xterm (or your favorite equivalent) on another machine and display it
+on your machine, you should not run an OPIE calculator in that window. When you
+type in your secret password, it still gets transmitted over the network to go
+to the machine the xterm is running on. People with machines such as
+X terminals that can only run the calculator over the network are in an
+especially precarious position because they really have no choice. Also, with
+the X Window System, as with some other window system (NeWS as an example),
+it is sometimes possible for people to read your keystrokes and capture your
+password even if you are running the OPIE calculator on your local machine.
+You should always use the best security mechanism available on your system to
+protect your X server, be it XDM-AUTHORIZATION-1, XDM-MAGIC-COOKIE-1, or host
+access control. *Never* just allow any machine to connect to your server
+because, by doing so, you are allowing any machine to read any of your windows
+or your keystrokes without you knowing it.
+
+.SH SEE ALSO
+.BR opie (4),
+.BR opiekeys (5),
+.BR opieaccess (5),
+.BR opiekey (1),
+.BR opieinfo (1),
+.BR opiepasswd (1),
+.BR opielogin (1),
+.BR opieftpd (8)
+.sp
+Lamport, L. "Password Authentication with Insecure Communication",
+Communications of the ACM 24.11 (November 1981), pp. 770-772.
+.sp
+Haller, N. "The S/KEY One-Time Password System", Proceedings of the ISOC
+Symposium on Network and Distributed System Security, February 1994,
+San Diego, CA.
+.sp
+Haller, N. and Atkinson, R, "On Internet Authentication", RFC-1704,
+DDN Network Information Center, October 1994.
+.sp
+Rivest, R. "The MD5 Message Digest Algorithm", RFC-1321,
+DDN Network Information Center, April 1992.
+.sp
+Rivest, R. "The MD4 Message Digest Algorithm", RFC-1320,
+DDN Network Information Center, April 1992.
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+UNIX is a trademark of X/Open.
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opie.h b/contrib/opie/opie.h
new file mode 100644
index 0000000..99f0e09
--- /dev/null
+++ b/contrib/opie/opie.h
@@ -0,0 +1,224 @@
+/* opie.h: Data structures and values for the OPIE authentication
+ system that a program might need.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Renamed PTR to VOIDPTR. Added
+ re-init key and extension file fields to struct opie. Added
+ opie_ prefix on struct opie members. Added opie_flags field
+ and definitions. Added more prototypes. Changed opiehash()
+ prototype.
+ Modified by cmetz for OPIE 2.22. Define __P correctly if this file
+ is included in a third-party program.
+ Modified by cmetz for OPIE 2.2. Re-did prototypes. Added FUNCTION
+ definition et al. Multiple-include protection. Added struct
+ utsname fake. Got rid of gethostname() cruft. Moved UINT4
+ here. Provide for *seek whence values. Move MDx context here
+ and unify. Re-did prototypes.
+ Modified at NRL for OPIE 2.0.
+ Written at Bellcore for the S/Key Version 1 software distribution
+ (skey.h).
+*/
+#ifndef _OPIE_H
+#define _OPIE_H
+
+#if _OPIE
+
+#if HAVE_VOIDPTR
+#define VOIDPTR void *
+#else /* HAVE_VOIDPTR */
+#define VOIDPTR char *
+#endif /* HAVE_VOIDPTR */
+
+#if HAVE_VOIDRET
+#define VOIDRET void
+#else /* HAVE_VOIDRET */
+#define VOIDRET
+#endif /* HAVE_VOIDRET */
+
+#if HAVE_VOIDARG
+#define NOARGS void
+#else /* HAVE_VOIDARG */
+#define NOARGS
+#endif /* HAVE_VOIDARG */
+
+#if HAVE_ANSIDECL
+#define FUNCTION(arglist, args) (args)
+#define AND ,
+#else /* HAVE_ANSIDECL */
+#define FUNCTION(arglist, args) arglist args;
+#define AND ;
+#endif /* HAVE_ANSIDECL */
+
+#define FUNCTION_NOARGS ()
+
+#ifndef __P
+#if HAVE_ANSIPROTO
+#define __P(x) x
+#else /* HAVE_ANSIPROTO */
+#define __P(x) ()
+#endif /* HAVE_ANSIPROTO */
+#endif /* __P */
+
+#ifndef HAVE_SYS_UTSNAME_H
+struct utsname {
+ char nodename[65];
+ };
+#endif /* HAVE_SYS_UTSNAME_H */
+
+#ifndef _SC_OPEN_MAX
+#define _SC_OPEN_MAX 1
+#endif /* _SC_OPEN_MAX */
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 1024
+#endif /* MAXHOSTNAMELEN */
+
+#else /* _OPIE */
+#ifdef __STDC__
+#define VOIDRET void
+#define VOIDPTR void *
+#else /* __STDC__ */
+#define VOIDRET
+#define VOIDPTR char *
+#endif /* __STDC__ */
+#endif /* _OPIE */
+
+#ifndef __P
+#ifdef __ARGS
+#define __P __ARGS
+#else /* __ARGS */
+#ifdef __STDC__
+#define __P(x) x
+#else /* __STDC__ */
+#define __P(x) ()
+#endif /* __STDC__ */
+#endif /* __ARGS */
+#endif /* __P */
+
+struct opie {
+ int opie_flags;
+ char opie_buf[256];
+ char *opie_principal;
+ int opie_n;
+ char *opie_seed;
+ char *opie_val;
+ long opie_recstart;
+ char opie_extbuf[129]; /* > OPIE_PRINCIPAL_MAX + 1 + 16 + 2 + 1 */
+ long opie_extrecstart;
+ char *opie_reinitkey;
+};
+
+#define __OPIE_FLAGS_RW 1
+#define __OPIE_FLAGS_READ 2
+
+/* Minimum length of a secret password */
+#ifndef OPIE_SECRET_MIN
+#define OPIE_SECRET_MIN 10
+#endif /* OPIE_SECRET_MIN */
+
+/* Maximum length of a secret password */
+#ifndef OPIE_SECRET_MAX
+#define OPIE_SECRET_MAX 127
+#endif /* OPIE_SECRET_MAX */
+
+/* Minimum length of a seed */
+#ifndef OPIE_SEED_MIN
+#define OPIE_SEED_MIN 5
+#endif /* OPIE_SEED_MIN */
+
+/* Maximum length of a seed */
+#ifndef OPIE_SEED_MAX
+#define OPIE_SEED_MAX 16
+#endif /* OPIE_SEED_MAX */
+
+/* Maximum length of a challenge (otp-md? 9999 seed) */
+#ifndef OPIE_CHALLENGE_MAX
+#define OPIE_CHALLENGE_MAX (7+1+4+1+OPIE_SEED_MAX)
+#endif /* OPIE_CHALLENGE_MAX */
+
+/* Maximum length of a response that we allow */
+#ifndef OPIE_RESPONSE_MAX
+#define OPIE_RESPONSE_MAX (9+1+19+1+9+OPIE_SEED_MAX+1+19+1+19+1+19)
+#endif /* OPIE_RESPONSE_MAX */
+
+/* Maximum length of a principal (read: user name) */
+#ifndef OPIE_PRINCIPAL_MAX
+#define OPIE_PRINCIPAL_MAX 32
+#endif /* OPIE_PRINCIPAL_MAX */
+
+#ifndef __alpha
+#define UINT4 unsigned long
+#else /* __alpha */
+#define UINT4 unsigned int
+#endif /* __alpha */
+
+struct opiemdx_ctx {
+ UINT4 state[4];
+ UINT4 count[2];
+ unsigned char buffer[64];
+};
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif /* SEEK_SET */
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif /* SEEK_END */
+
+int opieaccessfile __P((char *));
+int rdnets __P((long));
+int isaddr __P((register char *));
+int opiealways __P((char *));
+char *opieatob8 __P((char *,char *));
+VOIDRET opiebackspace __P((char *));
+char *opiebtoa8 __P((char *,char *));
+char *opiebtoe __P((char *,char *));
+char *opiebtoh __P((char *,char *));
+int opieetob __P((char *,char *));
+int opiechallenge __P((struct opie *,char *,char *));
+int opiegenerator __P((char *,char *,char *));
+int opiegetsequence __P((struct opie *));
+VOIDRET opiehash __P((VOIDPTR, unsigned));
+int opiehtoi __P((register char));
+int opiekeycrunch __P((int, char *, char *, char *));
+int opielock __P((char *));
+int opielookup __P((struct opie *,char *));
+VOIDRET opiemd4init __P((struct opiemdx_ctx *));
+VOIDRET opiemd4update __P((struct opiemdx_ctx *,unsigned char *,unsigned int));
+VOIDRET opiemd4final __P((unsigned char *,struct opiemdx_ctx *));
+VOIDRET opiemd5init __P((struct opiemdx_ctx *));
+VOIDRET opiemd5update __P((struct opiemdx_ctx *,unsigned char *,unsigned int));
+VOIDRET opiemd5final __P((unsigned char *,struct opiemdx_ctx *));
+int opiepasscheck __P((char *));
+VOIDRET opierandomchallenge __P((char *));
+char * opieskipspace __P((register char *));
+VOIDRET opiestripcrlf __P((char *));
+int opieverify __P((struct opie *,char *));
+int opiepasswd __P((struct opie *, int, char *, int, char *, char *));
+char *opiereadpass __P((char *, int, int));
+int opielogin __P((char *line, char *name, char *host));
+
+#if _OPIE
+struct utmp;
+int __opiegetutmpentry __P((char *, struct utmp *));
+#ifdef EOF
+FILE *__opieopen __P((char *, int, int));
+#endif /* EOF */
+int __opiereadrec __P((struct opie *));
+int __opiewriterec __P((struct opie *));
+#endif /* _OPIE */
+#endif /* _OPIE_H */
diff --git a/contrib/opie/opie_cfg.h b/contrib/opie/opie_cfg.h
new file mode 100644
index 0000000..57490de
--- /dev/null
+++ b/contrib/opie/opie_cfg.h
@@ -0,0 +1,167 @@
+/* opie_cfg.h: Various configuration-type pieces of information for OPIE.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Splatted with opie_auto.h.
+ Obseleted many symbols. Changed OPIE_PASS_{MIN,MAX} to
+ OPIE_SECRET_{MIN,MAX}. Fixed SHADOW+UTMP definitions.
+ Removed a lot of symbols.
+ Modified by cmetz for OPIE 2.2. Got rid of ANSIPROTO and ARGS.
+ Got rid of TRUE and FALSE definitions. Moved UINT4 to
+ opie.h and removed UINT2.
+ Modified at NRL for OPIE 2.1. Fixed sigprocmask declaration.
+ Gutted for autoconf. Split up for autoconf.
+ Written at NRL for OPIE 2.0.
+
+ History of opie_auto.h:
+
+ Modified by cmetz for OPIE 2.22. Support the Solaris TTYPROMPT drain
+ bamage on all systems -- it doesn't hurt others, and it's
+ not something Autoconf can check for yet.
+ Modified by cmetz for OPIE 2.2. Don't replace sigprocmask by ifdef.
+ Added configure check for LS_COMMAND. Added setreuid/setgid
+ band-aids.
+ Modified at NRL for OPIE 2.2. Require /etc/shadow for Linux to use
+ shadow passwords.
+ Modified at NRL for OPIE 2.11. Removed version defines.
+ Modified at NRL for OPIE 2.1. Fixed sigprocmask declaration.
+ Gutted for autoconf. Split up for autoconf.
+ Written at NRL for OPIE 2.0.
+*/
+
+#define VERSION "2.3"
+#define DATE "Sunday, September 22, 1996"
+
+#ifndef unix
+#define unix 1
+#endif /* unix */
+
+#include "config.h"
+#include "options.h"
+
+/* System characteristics */
+
+#if HAVE_GETUTXLINE && HAVE_UTMPX_H
+#define DOUTMPX 1
+#else /* HAVE_GETUTXLINE && HAVE_UTMPX_H */
+#define DOUTMPX 0
+#endif /* HAVE_GETUTXLINE && HAVE_UTMPX_H */
+
+/* Adapted from the Autoconf hypertext info pages */
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#else /* HAVE_DIRENT_H */
+#define dirent direct
+#if HAVE_SYS_NDIR_H
+#include <sys/ndir.h>
+#endif /* HAVE_SYS_NDIR_H */
+#if HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif /* HAVE_SYS_DIR_H */
+#if HAVE_NDIR_H
+#include <ndir.h>
+#endif /* HAVE_NDIR_H */
+#endif /* HAVE_DIRENT_H */
+
+#ifndef MAIL_DIR
+#ifdef PATH_MAIL
+#define MAIL_DIR PATH_MAIL
+#else /* PATH_MAIL */
+#ifdef _PATH_MAIL
+#define MAIL_DIR _PATH_MAIL
+#else /* _PATH_MAIL */
+#ifdef _PATH_MAILDIR
+#define MAIL_DIR _PATH_MAILDIR
+#else /* _PATH_MAILDIR */
+#define MAIL_DIR "/usr/spool/mail"
+#endif /* _PATH_MAILDIR */
+#endif /* _PATH_MAIL */
+#endif /* PATH_MAIL */
+#endif /* MAIL_DIR */
+
+#if HAVE_SHADOW_H && HAVE_GETSPENT && HAVE_ENDSPENT
+#if defined(linux) && !HAVE_ETC_SHADOW
+#define HAVE_SHADOW 0
+#else /* defined(linux) && !HAVE_ETC_SHADOW */
+#define HAVE_SHADOW 1
+#endif /* defined(linux) && !HAVE_ETC_SHADOW */
+#endif /* HAVE_SHADOW_H && HAVE_GETSPENT && HAVE_ENDSPENT */
+
+#if !HAVE_SETEUID && HAVE_SETREUID
+#define seteuid(x) setreuid(-1, x)
+#endif /* !HAVE_SETEUID && HAVE_SETREUID */
+
+#if !HAVE_SETEGID && HAVE_SETREGID
+#define setegid(x) setregid(-1, x)
+#endif /* !HAVE_SETEGID && HAVE_SETREGID */
+
+/* If the user didn't specify, default to MD5 */
+#ifndef MDX
+#define MDX 5
+#endif /* MDX */
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#ifndef _PATH_FTPUSERS
+#define _PATH_FTPUSERS "/etc/ftpusers"
+#endif
+
+#ifndef TTYGRPNAME
+#define TTYGRPNAME "tty" /* name of group to own ttys */
+#endif
+
+#ifndef NO_LOGINS_FILE
+#define NO_LOGINS_FILE "/etc/nologin"
+#endif
+
+#ifndef QUIET_LOGIN_FILE
+#define QUIET_LOGIN_FILE ".hushlogin"
+#endif
+
+#ifndef OPIE_ALWAYS_FILE
+#define OPIE_ALWAYS_FILE ".opiealways"
+#endif
+
+#ifndef OPIE_LOCK_PREFIX
+#define OPIE_LOCK_PREFIX "/tmp/opie-lock."
+#endif
+
+#ifndef OPIE_LOCK_TIMEOUT
+#define OPIE_LOCK_TIMEOUT (30*60)
+#endif
+
+#ifndef MOTD_FILE
+#define MOTD_FILE "/etc/motd"
+#endif
+
+#ifndef NBBY
+#define NBBY 8 /* Reasonable for modern systems */
+#endif /* NBBY */
+
+#ifndef LOGIN_PATH
+#define LOGIN_PATH "/usr/ucb:/bin:/usr/bin"
+#endif /* LOGIN_PATH */
+
+#ifndef POINTER
+#define POINTER unsigned char *
+#endif /* POINTER */
+
+#define _OPIE 1
diff --git a/contrib/opie/opieaccess.5 b/contrib/opie/opieaccess.5
new file mode 100644
index 0000000..33ab6dd
--- /dev/null
+++ b/contrib/opie/opieaccess.5
@@ -0,0 +1,87 @@
+.\" opieaccess.5: Manual page describing the /etc/opieaccess file.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Written at NRL for OPIE 2.0.
+.\"
+.ll 6i
+.pl 10.5i
+.\" @(#)opieaccess.5 2.0 (NRL) 1/10/95
+.\"
+.lt 6.0i
+.TH OPIEACCESS 5 "January 10, 1995"
+.AT 3
+.SH NAME
+[/etc/]opieaccess \- OPIE database of trusted networks
+
+.SH DESCRIPTION
+The
+.I opieaccess
+file contains a list of networks that are considered trusted by the system as
+far as security against passive attacks is concerned. Users from networks so
+trusted will be able to log in using OPIE responses, but not be required to
+do so, while users from networks that are not trusted will always be required
+to use OPIE responses (the default behavior). This trust allows a site to
+have a more gentle migration to OPIE by allowing it to be non-mandatory for
+"inside" networks while allowing users to choose whether they with to use OPIE
+to protect their passwords or not.
+.sp
+The entire notion of trust implemented in the
+.I opieaccess
+file is a major security hole because it opens your system back up to the same
+passive attacks that the OPIE system is designed to protect you against. The
+.I opieaccess
+support in this version of OPIE exists solely because we believe that it is
+better to have it so that users who don't want their accounts broken into can
+use OPIE than to have them prevented from doing so by users who don't want
+to use OPIE. In any environment, it should be considered a transition tool and
+not a permanent fixture. When it is not being used as a transition tool, a
+version of OPIE that has been built without support for the
+.I opieaccess
+file should be built to prevent the possibility of an attacker using this file
+as a means to circumvent the OPIE software.
+.sp
+The
+.I opieaccess
+file consists of lines containing three fields separated by spaces (tabs are
+properly interpreted, but spaces should be used instead) as follows:
+.PP
+.nf
+.ta \w' 'u
+Field Description
+action "permit" or "deny" non-OPIE logins
+address Address of the network to match
+mask Mask of the network to match
+.fi
+
+Subnets can be controlled by using the appropriate address and mask. Individual
+hosts can be controlled by using the appropriate address and a mask of
+255.255.255.255. If no rules are matched, the default is to deny non-0PIE
+logins.
+
+.SH SEE ALSO
+.BR opie (4),
+.BR opiekeys (5),
+.BR opiepasswd (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8)
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opieftpd.8 b/contrib/opie/opieftpd.8
new file mode 100644
index 0000000..1943ce9
--- /dev/null
+++ b/contrib/opie/opieftpd.8
@@ -0,0 +1,280 @@
+.\" opieftpd.8: Manual page describing the FTP daemon.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Modified at NRL for OPIE 2.0.
+.\" Originally from BSD.
+.\"
+.\" NOTE:
+.\"
+.\" This manual page uses the BSD >= Net/2 "mandoc" macros and may not
+.\" format properly on all systems.
+.\"
+.\" Copyright (c) 1985, 1988, 1991 The Regents of the University of California.
+.\" 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)opieopieftpd.8 6.9 (Berkeley) 3/16/91
+.\"
+.TH OPIEFTPD 8 "10 January 1995"
+
+.SH NAME
+opieftpd \- File Transfer Protocol server that uses OPIE authentication
+
+.SH SYNOPSIS
+.B opieftpd
+[\-d] [\-l] [\-t
+.I timeout
+] [\-T
+.I maxtimeout
+]
+
+.SH DESCRIPTION
+.I opieftpd
+is the Internet File Transfer Protocol server process. The server uses the
+TCP protocol and listens at the port specified in the ftp service
+specification; see
+.IR services (5).
+
+.SH OPTIONS
+.TP
+.B \-d
+Debugging information is written to the system logs.
+.TP
+.B \-l
+Each
+.IR ftp (1)
+session is logged in the system logs.
+.TP
+.B \-t
+The inactivity timeout period is set to
+.I timeout
+seconds (the default is 15 minutes).
+.TP
+.B \-T
+A client may also request a different timeout period;
+the maximum period allowed may be set to
+.I maxtimeout
+seconds with the
+.B \-T
+option. The default limit is 2 hours.
+.SH COMMANDS
+The ftp server currently supports the following ftp
+requests; case is not distinguished:
+.PP
+.nf
+.ta \w'Request 'u
+Request Description
+ABOR abort previous command
+ACCT specify account (ignored)
+ALLO allocate storage (vacuously)
+APPE append to a file
+CDUP change to parent of current working directory
+CWD change working directory
+DELE delete a file
+HELP give help information
+LIST give a list of files in a directory
+MKD make a directory
+MDTM show last modification time of file
+MODE specify data transfer mode
+NLST give name list of files in directory
+NOOP do nothing
+PASS specify password
+PASV prepare for server-to-server transfer
+PORT specify data connection port
+PWD print the current working directory
+QUIT terminate session
+REST restart incomplete transfer
+RETR retrieve a file
+RMD remove a directory
+RNFR specify rename-from file name
+RNTO specify rename-to file name
+SITE non-standard commands (see next section)
+SIZE return size of file
+STAT return status of server
+STOR store a file
+STOU store a file with a unique name
+STRU specify data transfer structure
+SYST show operating system type of server system
+TYPE specify data transfer type
+USER specify user name
+XCUP change to parent of current working directory (deprecated)
+XCWD change working directory (deprecated)
+XMKD make a directory (deprecated)
+XPWD print the current working directory (deprecated)
+XRMD remove a directory (deprecated)
+.fi
+
+The following non-standard or UNIX-specific commands are supported
+by the SITE request:
+.PP
+.nf
+.ta \w'Request 'u
+Request Description
+UMASK change umask (e.g. SITE UMASK 002)
+IDLE set idle-timer (e.g. SITE IDLE 60)
+CHMOD change mode of a file (e.g. SITE CHMOD 755 file)
+HELP give help information (e.g. SITE HELP)
+.fi
+.sp
+The remaining ftp requests specified in Internet RFC-959 are
+recognized, but not implemented.
+.sp
+MDTM and SIZE are not specified in RFC-959, but will appear
+in the next updated FTP RFC.
+
+The ftp server will abort an active file transfer only when the
+ABOR command is preceded by a Telnet "Interrupt Process" (IP)
+signal and a Telnet "Synch" signal in the command Telnet stream,
+as described in Internet RFC-959.
+If a STAT command is received during a data transfer, preceded by
+a Telnet IP and Synch, transfer status will be returned.
+.I opieftpd
+interprets file names according to the globbing conventions used by
+.IR csh (1).
+This allows users to utilize the metacharacters
+\&*?[]{}~.
+.sp
+.I opieftpd
+authenticates users according to three rules:
+.sp
+The user name must be in the password data base,
+.I /etc/passwd,
+and not have a null password. In this case, a password
+must be provided by the client before any file operations
+may be performed.
+.sp
+The user name must not appear in the file
+.I /etc/ftpusers.
+.sp
+The user must have a standard shell returned by
+.IR getusershell (3).
+.sp
+If the user name is
+.I anonymous
+or
+.I ftp,
+an anonymous ftp account must be present in the password
+file (user
+.I ftp ).
+In this case, the user is allowed to log in by specifying any
+password (by convention, this is given as the client host's name).
+
+In the last case,
+.I opieftpd
+takes special measures to restrict the client's access privileges.
+The server performs a
+.IR chroot (2)
+command to the home directory of the
+.I ftp
+user.
+In order that system security is not breached, it is recommended
+that the
+.I ftp
+subtree be constructed with care; the following
+rules are recommended:
+.sp
+.TP
+.B ~ftp
+Make the home directory owned by
+.I ftp
+and unwritable by anyone.
+.TP
+.B ~ftp/bin
+Make this directory owned by the super-user and unwritable by
+anyone. The program
+.IR ls (1)
+must be present to support the LIST command. This
+program should have mode 111.
+.TP
+.B ~ftp/etc
+Make this directory owned by the super-user and unwritable by
+anyone. The files
+.IR passwd (5)
+and
+.IR group (5)
+must be present for the
+.IR ls (1)
+command to be able to produce owner names rather than numbers.
+The password field in
+.I passwd
+is not used, and should not contain real encrypted passwords.
+These files should be mode 444.
+.TP
+.B ~ftp/pub
+Make this directory mode 777 and owned by
+.I ftp.
+Users should then place files which are to be accessible via the
+anonymous account in this directory.
+.SH SEE ALSO
+.BR ftpd (8),
+.BR ftp (1),
+.BR opie (4),
+.BR opiekey (1),
+.BR opiepasswd (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opieftpd (8),
+.BR opiekeys (5),
+.BR opieaccess (5)
+
+.SH BUGS
+The anonymous account is inherently dangerous and should
+avoided when possible. In
+.I opieftpd,
+it is a compile-time option that should be disabled if it is not
+being used.
+The server must run as the super-user
+to create sockets with privileged port numbers. It maintains
+an effective user id of the logged in user, reverting to
+the super-user only when binding addresses to sockets. The
+possible security holes have been scrutinized, but are possibly incomplete.
+
+.SH HISTORY
+The
+.I ftpd
+command appeared in 4.2BSD.
+
+.SH AUTHOR
+Originally written for BSD,
+.I ftpd
+was modified at NRL by Randall Atkinson, Dan McDonald, and Craig Metz to
+support OTP authentication.
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opieftpd.c b/contrib/opie/opieftpd.c
new file mode 100644
index 0000000..b11ece4
--- /dev/null
+++ b/contrib/opie/opieftpd.c
@@ -0,0 +1,1643 @@
+/* opieftpd.c: Main program for an FTP daemon.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Fixed the filename at the top.
+ Moved LS_COMMAND here.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION definition et al.
+ Removed useless strings (I don't think that removing the
+ ucb copyright one is a problem -- please let me know if
+ I'm wrong). Changed default CMASK to 077. Removed random
+ comments. Use ANSI stdargs for reply/lreply if we can,
+ added stdargs version of reply/lreply. Don't declare the
+ tos variable unless IP_TOS defined. Include stdargs headers
+ early. More headers ifdefed. Made everything static.
+ Got rid of gethostname() call and use of hostname. Pared
+ down status response for places where header files frequently
+ cause trouble. Made logging of user logins (ala -l)
+ non-optional. Moved reply()/lrepy(). Fixed some prototypes.
+ Modified at NRL for OPIE 2.1. Added declaration of envp. Discard
+ result of opiechallenge (allows access control to work).
+ Added patches for AIX. Symbol changes for autoconf.
+ Modified at NRL for OPIE 2.01. Changed password lookup handling
+ to avoid problems with drain-bamaged shadow password packages.
+ Properly handle internal state for anonymous FTP. Unlock
+ user accounts properly if login fails because of /etc/shells.
+ Make sure to close syslog by function to avoid problems with
+ drain bamaged syslog implementations.
+ Modified at NRL for OPIE 2.0.
+ Originally from BSD Net/2.
+
+ There is some really, really ugly code in here.
+*/
+/*
+ * Copyright (c) 1985, 1988, 1990 Regents of the University of California.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 "opie_cfg.h"
+
+#if HAVE_ANSISTDARG
+#include <stdarg.h>
+#endif /* HAVE_ANSISTDARG */
+
+/*
+ * FTP server.
+ */
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#include <sys/stat.h>
+/* #include <sys/ioctl.h> */
+#include <sys/socket.h>
+#include <sys/wait.h>
+#ifdef SYS_FCNTL_H
+#include <sys/fcntl.h>
+#else
+#include <fcntl.h>
+#endif /* SYS_FCNTL_H */
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#define FTP_NAMES
+#include <arpa/ftp.h>
+#include <arpa/inet.h>
+#include <arpa/telnet.h>
+
+#include <signal.h>
+#include <dirent.h>
+#include <fcntl.h>
+#if HAVE_TIME_H
+#include <time.h>
+#endif /* HAVE_TIME_H */
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif /* HAVE_PWD_H */
+#include <setjmp.h>
+#include <netdb.h>
+#include <errno.h>
+#include <syslog.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grp.h>
+
+#include "opie.h"
+
+#if HAVE_SHADOW_H
+#include <shadow.h>
+#endif /* HAVE_SHADOW_H */
+
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif /* HAVE_CRYPT_H */
+
+#if HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif /* HAVE_SYS_UTSNAME_H */
+
+#ifdef _AIX
+#include <sys/id.h>
+#include <sys/priv.h>
+#endif /* _AIX */
+
+#ifdef IP_TOS
+#ifndef IPTOS_THROUGHPUT
+#undef IP_TOS
+#endif /* !IPTOS_THROUGHPUT */
+#ifndef IPTOS_LOWDELAY
+#undef IP_TOS
+#endif /* !IPTOS_LOWDELAY */
+#endif /* IP_TOS */
+
+extern int errno;
+extern char *home; /* pointer to home directory for glob */
+extern FILE *ftpd_popen __P((char *, char *));
+extern int ftpd_pclose __P((FILE *));
+extern char cbuf[];
+extern off_t restart_point;
+
+static struct sockaddr_in ctrl_addr;
+static struct sockaddr_in data_source;
+struct sockaddr_in data_dest;
+struct sockaddr_in his_addr;
+static struct sockaddr_in pasv_addr;
+
+static int data;
+jmp_buf errcatch;
+static jmp_buf urgcatch;
+int logged_in;
+struct passwd *pw;
+int debug;
+int timeout = 900; /* timeout after 15 minutes of inactivity */
+int maxtimeout = 7200; /* don't allow idle time to be set beyond 2 hours */
+
+#if DOANONYMOUS
+static int guest;
+#endif /* DOANONYMOUS */
+int type;
+int form;
+static int stru; /* avoid C keyword */
+static int mode;
+int usedefault = 1; /* for data transfers */
+int pdata = -1; /* for passive mode */
+static int transflag;
+static off_t file_size;
+static off_t byte_count;
+
+#if (!defined(CMASK) || CMASK == 0)
+#undef CMASK
+#define CMASK 077
+#endif
+
+static int defumask = CMASK; /* default umask value */
+char tmpline[7];
+char remotehost[MAXHOSTNAMELEN];
+
+/*
+ * Timeout intervals for retrying connections
+ * to hosts that don't accept PORT cmds. This
+ * is a kludge, but given the problems with TCP...
+ */
+#define SWAITMAX 90 /* wait at most 90 seconds */
+#define SWAITINT 5 /* interval between retries */
+
+static int swaitmax = SWAITMAX;
+static int swaitint = SWAITINT;
+
+#if DOTITLE
+static char **Argv = NULL; /* pointer to argument vector */
+static char *LastArgv = NULL; /* end of argv */
+static char proctitle[BUFSIZ]; /* initial part of title */
+#endif /* DOTITLE */
+
+static int af_pwok = 0, pwok = 0;
+static struct opie opiestate;
+
+VOIDRET perror_reply __P((int, char *));
+VOIDRET dologout __P((int));
+char *getline __P((char *, int, FILE *));
+VOIDRET upper __P((char *));
+
+static VOIDRET lostconn __P((int));
+static FILE *getdatasock __P((char *));
+static FILE *dataconn __P((char *, off_t, char *));
+static int checkuser __P((char *));
+static VOIDRET end_login __P((void));
+static VOIDRET send_data __P((FILE *, FILE *, off_t));
+static int receive_data __P((FILE *, FILE *));
+static char *gunique __P((char *));
+static char *sgetsave __P((char *));
+
+int logwtmp __P((char *, char *, char *));
+
+int fclose __P((FILE *));
+
+#ifdef HAVE_ANSISTDARG
+VOIDRET reply FUNCTION((stdarg is ANSI only), int n AND char *fmt AND ...)
+{
+ va_list ap;
+ char buffer[1024];
+
+ va_start(ap, fmt);
+ vsprintf(buffer, fmt, ap);
+ va_end(ap);
+
+ printf("%d %s\r\n", n, buffer);
+ fflush(stdout);
+ if (debug)
+ syslog(LOG_DEBUG, "<--- %d %s", n, buffer);
+}
+#else /* HAVE_ANSISTDARG */
+VOIDRET reply FUNCTION((n, fmt, p0, p1, p2, p3, p4, p5), int n AND char *fmt AND int p0 AND int p1 AND int p2 AND int p3 AND int p4 AND int p5)
+{
+ printf("%d ", n);
+ printf(fmt, p0, p1, p2, p3, p4, p5);
+ printf("\r\n");
+ fflush(stdout);
+ if (debug) {
+ syslog(LOG_DEBUG, "<--- %d ", n);
+ syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5);
+ }
+}
+#endif /* HAVE_ANSISTDARG */
+
+#ifdef HAVE_ANSISTDARG
+VOIDRET lreply FUNCTION((stdarg is ANSI only), int n AND char *fmt AND ...)
+{
+ va_list ap;
+ char buffer[1024];
+
+ va_start(ap, fmt);
+ vsprintf(buffer, fmt, ap);
+ va_end(ap);
+
+ printf("%d- %s\r\n", n, buffer);
+ fflush(stdout);
+ if (debug)
+ syslog(LOG_DEBUG, "<--- %d- %s", n, buffer);
+}
+#else /* HAVE_ANSISTDARG */
+VOIDRET lreply FUNCTION((n, fmt, p0, p1, p2, p3, p4, p5), int n AND char *fmt AND int p0 AND int p1 AND int p2 AND int p3 AND int p4 AND int p5)
+{
+ printf("%d- ", n);
+ printf(fmt, p0, p1, p2, p3, p4, p5);
+ printf("\r\n");
+ fflush(stdout);
+ if (debug) {
+ syslog(LOG_DEBUG, "<--- %d- ", n);
+ syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5);
+ }
+}
+#endif /* HAVE_ANSISTDARG */
+
+static VOIDRET lostconn FUNCTION((input), int input)
+{
+ if (debug)
+ syslog(LOG_DEBUG, "lost connection");
+ dologout(-1);
+}
+
+static char ttyline[20];
+
+/*
+ * Helper function for sgetpwnam().
+ */
+static char *sgetsave FUNCTION((s), char *s)
+{
+ char *new = malloc((unsigned) strlen(s) + 1);
+
+ if (new == NULL) {
+ perror_reply(421, "Local resource failure: malloc");
+ dologout(1);
+ /* NOTREACHED */
+ }
+ strcpy(new, s);
+ return (new);
+}
+
+/*
+ * Save the result of a getpwnam. Used for USER command, since
+ * the data returned must not be clobbered by any other command
+ * (e.g., globbing).
+ */
+static struct passwd *sgetpwnam FUNCTION((name), char *name)
+{
+ static struct passwd save;
+ register struct passwd *p;
+
+#if HAVE_SHADOW
+ struct spwd *spwd;
+#endif /* HAVE_SHADOW */
+
+ if ((p = getpwnam(name)) == NULL)
+ return (p);
+
+#if HAVE_SHADOW
+ if ((spwd = getspnam(name)) == NULL)
+ return NULL;
+
+ endspent();
+
+ p->pw_passwd = spwd->sp_pwdp;
+#endif /* HAVE_SHADOW */
+
+ endpwent();
+
+ if (save.pw_name) {
+ free(save.pw_name);
+ free(save.pw_passwd);
+ free(save.pw_gecos);
+ free(save.pw_dir);
+ free(save.pw_shell);
+ }
+ save = *p;
+ save.pw_name = sgetsave(p->pw_name);
+ save.pw_passwd = sgetsave(p->pw_passwd);
+ save.pw_gecos = sgetsave(p->pw_gecos);
+ save.pw_dir = sgetsave(p->pw_dir);
+ save.pw_shell = sgetsave(p->pw_shell);
+ return (&save);
+}
+
+int login_attempts; /* number of failed login attempts */
+int askpasswd; /* had user command, ask for passwd */
+
+/*
+ * USER command.
+ * Sets global passwd pointer pw if named account exists and is acceptable;
+ * sets askpasswd if a PASS command is expected. If logged in previously,
+ * need to reset state. If name is "ftp" or "anonymous", the name is not in
+ * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
+ * If account doesn't exist, ask for passwd anyway. Otherwise, check user
+ * requesting login privileges. Disallow anyone who does not have a standard
+ * shell as returned by getusershell(). Disallow anyone mentioned in the file
+ * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
+ */
+int user FUNCTION((name), char *name)
+{
+ register char *cp;
+ char *shell;
+
+ if (logged_in) {
+#if DOANONYMOUS
+ if (guest) {
+ reply(530, "Can't change user from guest login.");
+ return -1;
+ }
+#endif /* DOANONMOUS */
+ end_login();
+ }
+ askpasswd = 1;
+#if DOANONYMOUS
+ guest = 0;
+ if (!strcmp(name, "ftp") || !strcmp(name, "anonymous"))
+ if (!checkuser("ftp") && !checkuser("anonymous"))
+ if ((pw = sgetpwnam("ftp")) != NULL) {
+ guest = 1;
+ askpasswd = 1;
+ reply(331, "Guest login ok, send ident as password.");
+ syslog(LOG_INFO, "Anonymous FTP connection made from host %s.",
+ remotehost);
+ return 0;
+ }
+#endif /* DOANONYMOUS */
+ if (pw = sgetpwnam(name)) {
+ if ((shell = pw->pw_shell) == NULL || *shell == 0)
+ shell = _PATH_BSHELL;
+ while ((cp = getusershell()) != NULL)
+ if (!strcmp(cp, shell))
+ break;
+ endusershell();
+ if (cp == NULL || checkuser(name) ||
+ ((pw->pw_passwd[0] == '*') || (pw->pw_passwd[0] == '#'))) {
+#if DEBUG
+ if (!cp)
+ syslog(LOG_DEBUG, "Couldn't find %s in the list of valid shells.", pw->pw_shell);
+ if (checkuser(name))
+ syslog(LOG_DEBUG, "checkuser failed - user in /etc/ftpusers?");
+ if (((pw->pw_passwd[0] == '*') || (pw->pw_passwd[0] == '#')))
+ syslog(LOG_DEBUG, "Login disabled: pw_passwd == %s", pw->pw_passwd);
+#endif /* DEBUG */
+ pw = (struct passwd *) NULL;
+ askpasswd = -1;
+ }
+ }
+ {
+ char prompt[OPIE_CHALLENGE_MAX + 1];
+
+ opiechallenge(&opiestate, name, prompt);
+
+ if (askpasswd == -1) {
+ syslog(LOG_WARNING, "Invalid FTP user name %s attempted from %s.", name, remotehost);
+ pwok = 0;
+ } else
+ pwok = af_pwok && opiealways(pw->pw_dir);
+
+#if NEW_PROMPTS
+ reply(331, "Response to %s %s for %s.", prompt,
+#else /* NEW_PROMPTS */
+ reply(331, "OTP response %s %s for %s.", prompt,
+#endif /* NEW_PROMPTS */
+ pwok ? "requested" : "required", name);
+ }
+ /* Delay before reading passwd after first failed attempt to slow down
+ passwd-guessing programs. */
+ if (login_attempts)
+ sleep((unsigned) login_attempts);
+
+ return 0;
+}
+
+/*
+ * Check if a user is in the file _PATH_FTPUSERS
+ */
+static int checkuser FUNCTION((name), char *name)
+{
+ register FILE *fd;
+ register char *p;
+ char line[BUFSIZ];
+
+ if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) {
+ while (fgets(line, sizeof(line), fd) != NULL)
+ if ((p = strchr(line, '\n')) != NULL) {
+ *p = '\0';
+ if (line[0] == '#')
+ continue;
+ if (strcmp(line, name) == 0)
+ return (1);
+ }
+ fclose(fd);
+ }
+ return (0);
+}
+
+/*
+ * Terminate login as previous user, if any, resetting state;
+ * used when USER command is given or login fails.
+ */
+static VOIDRET end_login FUNCTION_NOARGS
+{
+ if (seteuid((uid_t) 0))
+ syslog(LOG_ERR, "Can't set euid");
+ if (logged_in)
+ logwtmp(ttyline, "", "");
+ pw = NULL;
+ logged_in = 0;
+#if DOANONYMOUS
+ guest = 0;
+#endif /* DOANONYMOUS */
+}
+
+VOIDRET pass FUNCTION((passwd), char *passwd)
+{
+ int legit = askpasswd + 1, i;
+
+ if (logged_in || askpasswd == 0) {
+ reply(503, "Login with USER first.");
+ return;
+ }
+ askpasswd = 0;
+
+#if DOANONYMOUS
+ if (!guest) { /* "ftp" is only account allowed no password */
+#endif /* DOANONYMOUS */
+ i = opieverify(&opiestate, passwd);
+ if (legit && i && pwok)
+ i = strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd);
+ if (!legit || i) {
+ reply(530, "Login incorrect.");
+ pw = NULL;
+ if (login_attempts++ >= 5) {
+ syslog(LOG_WARNING,
+ "Repeated login failures for user %s from %s",
+ pw->pw_name, remotehost);
+ exit(0);
+ }
+ return;
+ }
+#if DOANONYMOUS
+ }
+#endif /* DOANONYMOUS */
+ login_attempts = 0; /* this time successful */
+ setegid((gid_t) pw->pw_gid);
+ initgroups(pw->pw_name, pw->pw_gid);
+
+ /* open wtmp before chroot */
+ sprintf(ttyline, "ftp%d", getpid());
+ logwtmp(ttyline, pw->pw_name, remotehost);
+ logged_in = 1;
+
+#if DOANONYMOUS
+ if (guest) {
+ /* We MUST do a chdir() after the chroot. Otherwise the old current
+ directory will be accessible as "." outside the new root! */
+ if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
+ reply(550, "Can't set guest privileges.");
+ goto bad;
+ }
+ } else
+#endif /* DOANONYMOUS */
+ if (chdir(pw->pw_dir) < 0) {
+ if (chdir("/") < 0) {
+ reply(530, "User %s: can't change directory to %s.",
+ pw->pw_name, pw->pw_dir);
+ goto bad;
+ } else
+ lreply(230, "No directory! Logging in with home=/");
+ }
+/* This patch was contributed by an OPIE user. We don't know what it
+ does, exactly. It may or may not work. */
+#ifdef _AIX
+ {
+ priv_t priv;
+ priv.pv_priv[0] = 0;
+ priv.pv_priv[1] = 0;
+ setgroups(NULL, NULL);
+ if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
+ &priv, sizeof(priv_t)) < 0 ||
+ setgidx(ID_REAL|ID_EFFECTIVE, (gid_t)pw->pw_gid) < 0 ||
+ setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)pw->pw_uid) < 0 ||
+ seteuid((uid_t)pw->pw_uid) < 0) {
+ reply(550, "Can't set uid (_AIX3).");
+ goto bad;
+ }
+ }
+#else /* _AIX */
+ if (seteuid((uid_t) pw->pw_uid) < 0) {
+ reply(550, "Can't set uid.");
+ goto bad;
+ }
+#endif /* _AIX */
+#if DOANONYMOUS
+ if (guest) {
+ reply(230, "Guest login ok, access restrictions apply.");
+#if DOTITLE
+ sprintf(proctitle, "%s: anonymous/%.*s", remotehost,
+ sizeof(proctitle) - sizeof(remotehost) -
+ sizeof(": anonymous/"), passwd);
+ setproctitle(proctitle);
+#endif /* DOTITLE */
+ syslog(LOG_NOTICE, "ANONYMOUS FTP login from %s with ID %s",
+ remotehost, passwd);
+ } else
+#endif /* DOANONYMOUS */
+ {
+ reply(230, "User %s logged in.", pw->pw_name);
+
+#if DOTITLE
+ sprintf(proctitle, "%s: %s", remotehost, pw->pw_name);
+ setproctitle(proctitle);
+#endif /* DOTITLE */
+ syslog(LOG_NOTICE, "FTP login from %s with user name %s",
+ remotehost, pw->pw_name);
+ }
+ home = pw->pw_dir; /* home dir for globbing */
+ umask(defumask);
+ return;
+
+bad:
+ /* Forget all about it... */
+ end_login();
+}
+
+VOIDRET retrieve FUNCTION((cmd, name), char *cmd AND char *name)
+{
+ FILE *fin, *dout;
+ struct stat st;
+ int (*closefunc) ();
+
+ if (cmd == 0) {
+ fin = fopen(name, "r"), closefunc = fclose;
+ st.st_size = 0;
+ } else {
+ char line[BUFSIZ];
+
+ sprintf(line, cmd, name), name = line;
+ fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
+ st.st_size = -1;
+#if HAVE_ST_BLKSIZE
+ st.st_blksize = BUFSIZ;
+#endif /* HAVE_ST_BLKSIZE */
+ }
+ if (fin == NULL) {
+ if (errno != 0)
+ perror_reply(550, name);
+ return;
+ }
+ if (cmd == 0 &&
+ (fstat(fileno(fin), &st) < 0 || (st.st_mode & S_IFMT) != S_IFREG)) {
+ reply(550, "%s: not a plain file.", name);
+ goto done;
+ }
+ if (restart_point) {
+ if (type == TYPE_A) {
+ register int i, n, c;
+
+ n = restart_point;
+ i = 0;
+ while (i++ < n) {
+ if ((c = getc(fin)) == EOF) {
+ perror_reply(550, name);
+ goto done;
+ }
+ if (c == '\n')
+ i++;
+ }
+ } else
+ if (lseek(fileno(fin), restart_point, SEEK_SET /* L_SET */ ) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ }
+ dout = dataconn(name, st.st_size, "w");
+ if (dout == NULL)
+ goto done;
+#if HAVE_ST_BLKSIZE
+ send_data(fin, dout, st.st_blksize);
+#else /* HAVE_ST_BLKSIZE */
+ send_data(fin, dout, BUFSIZ);
+#endif /* HAVE_ST_BLKSIZE */
+ fclose(dout);
+ data = -1;
+ pdata = -1;
+done:
+ (*closefunc) (fin);
+}
+
+VOIDRET store FUNCTION((name, mode, unique), char *name AND char *mode AND int unique)
+{
+ FILE *fout, *din;
+ struct stat st;
+ int (*closefunc) ();
+
+ if (unique && stat(name, &st) == 0 &&
+ (name = gunique(name)) == NULL)
+ return;
+
+ if (restart_point)
+ mode = "r+w";
+ fout = fopen(name, mode);
+ closefunc = fclose;
+ if (fout == NULL) {
+ perror_reply(553, name);
+ return;
+ }
+ if (restart_point) {
+ if (type == TYPE_A) {
+ register int i, n, c;
+
+ n = restart_point;
+ i = 0;
+ while (i++ < n) {
+ if ((c = getc(fout)) == EOF) {
+ perror_reply(550, name);
+ goto done;
+ }
+ if (c == '\n')
+ i++;
+ }
+ /* We must do this seek to "current" position because we are changing
+ from reading to writing. */
+ if (fseek(fout, 0L, SEEK_CUR /* L_INCR */ ) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ } else
+ if (lseek(fileno(fout), restart_point, SEEK_SET /* L_SET */ ) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ }
+ din = dataconn(name, (off_t) - 1, "r");
+ if (din == NULL)
+ goto done;
+ if (receive_data(din, fout) == 0) {
+ if (unique)
+ reply(226, "Transfer complete (unique file name:%s).",
+ name);
+ else
+ reply(226, "Transfer complete.");
+ }
+ fclose(din);
+ data = -1;
+ pdata = -1;
+done:
+ (*closefunc) (fout);
+}
+
+static FILE *getdatasock FUNCTION((mode), char *mode)
+{
+ int s, on = 1, tries;
+
+ if (data >= 0)
+ return (fdopen(data, mode));
+ if (seteuid((uid_t) 0))
+ syslog(LOG_ERR, "Can't set euid");
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ goto bad;
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &on, sizeof(on)) < 0)
+ goto bad;
+ /* anchor socket to avoid multi-homing problems */
+ data_source.sin_family = AF_INET;
+ data_source.sin_addr = ctrl_addr.sin_addr;
+ for (tries = 1;; tries++) {
+ if (bind(s, (struct sockaddr *) & data_source,
+ sizeof(data_source)) >= 0)
+ break;
+ if (errno != EADDRINUSE || tries > 10)
+ goto bad;
+ sleep(tries);
+ }
+ if (seteuid((uid_t) pw->pw_uid))
+ syslog(LOG_ERR, "Can't set euid");
+#ifdef IP_TOS
+ on = IPTOS_THROUGHPUT;
+ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &on, sizeof(int)) < 0)
+ syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+ return (fdopen(s, mode));
+bad:
+ if (seteuid((uid_t) pw->pw_uid))
+ syslog(LOG_ERR, "Can't set euid");
+ close(s);
+ return (NULL);
+}
+
+static FILE *dataconn FUNCTION((name, size, mode), char *name AND off_t size AND char *mode)
+{
+ char sizebuf[32];
+ FILE *file;
+ int retry = 0;
+#ifdef IP_TOS
+ int tos;
+#endif /* IP_TOS */
+
+ file_size = size;
+ byte_count = 0;
+ if (size != (off_t) - 1)
+ sprintf(sizebuf, " (%ld bytes)", size);
+ else
+ strcpy(sizebuf, "");
+ if (pdata >= 0) {
+ struct sockaddr_in from;
+ int s, fromlen = sizeof(from);
+
+ s = accept(pdata, (struct sockaddr *) & from, &fromlen);
+ if (s < 0) {
+ reply(425, "Can't open data connection.");
+ close(pdata);
+ pdata = -1;
+ return (NULL);
+ }
+ close(pdata);
+ pdata = s;
+#ifdef IP_TOS
+ tos = IPTOS_LOWDELAY;
+ setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &tos,
+ sizeof(int));
+
+#endif
+ reply(150, "Opening %s mode data connection for %s%s.",
+ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+ return (fdopen(pdata, mode));
+ }
+ if (data >= 0) {
+ reply(125, "Using existing data connection for %s%s.",
+ name, sizebuf);
+ usedefault = 1;
+ return (fdopen(data, mode));
+ }
+ if (usedefault)
+ data_dest = his_addr;
+ usedefault = 1;
+ file = getdatasock(mode);
+ if (file == NULL) {
+ reply(425, "Can't create data socket (%s,%d): %s.",
+ inet_ntoa(data_source.sin_addr),
+ ntohs(data_source.sin_port), strerror(errno));
+ return (NULL);
+ }
+ data = fileno(file);
+ while (connect(data, (struct sockaddr *) & data_dest,
+ sizeof(data_dest)) < 0) {
+ if (errno == EADDRINUSE && retry < swaitmax) {
+ sleep((unsigned) swaitint);
+ retry += swaitint;
+ continue;
+ }
+ perror_reply(425, "Can't build data connection");
+ fclose(file);
+ data = -1;
+ return (NULL);
+ }
+ reply(150, "Opening %s mode data connection for %s%s.",
+ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+ return (file);
+}
+
+/*
+ * Tranfer the contents of "instr" to
+ * "outstr" peer using the appropriate
+ * encapsulation of the data subject
+ * to Mode, Structure, and Type.
+ *
+ * NB: Form isn't handled.
+ */
+static VOIDRET send_data FUNCTION((instr, outstr, blksize), FILE *instr AND FILE *outstr AND off_t blksize)
+{
+ register int c, cnt;
+ register char *buf;
+ int netfd, filefd;
+
+ transflag++;
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ return;
+ }
+ switch (type) {
+
+ case TYPE_A:
+ while ((c = getc(instr)) != EOF) {
+ byte_count++;
+ if (c == '\n') {
+ if (ferror(outstr))
+ goto data_err;
+ putc('\r', outstr);
+ }
+ putc(c, outstr);
+ }
+ fflush(outstr);
+ transflag = 0;
+ if (ferror(instr))
+ goto file_err;
+ if (ferror(outstr))
+ goto data_err;
+ reply(226, "Transfer complete.");
+ return;
+
+ case TYPE_I:
+ case TYPE_L:
+ if ((buf = malloc((u_int) blksize)) == NULL) {
+ transflag = 0;
+ perror_reply(451, "Local resource failure: malloc");
+ return;
+ }
+ netfd = fileno(outstr);
+ filefd = fileno(instr);
+ while ((cnt = read(filefd, buf, (u_int) blksize)) > 0 &&
+ write(netfd, buf, cnt) == cnt)
+ byte_count += cnt;
+ transflag = 0;
+ free(buf);
+ if (cnt != 0) {
+ if (cnt < 0)
+ goto file_err;
+ goto data_err;
+ }
+ reply(226, "Transfer complete.");
+ return;
+ default:
+ transflag = 0;
+ reply(550, "Unimplemented TYPE %d in send_data", type);
+ return;
+ }
+
+data_err:
+ transflag = 0;
+ perror_reply(426, "Data connection");
+ return;
+
+file_err:
+ transflag = 0;
+ perror_reply(551, "Error on input file");
+}
+
+/*
+ * Transfer data from peer to
+ * "outstr" using the appropriate
+ * encapulation of the data subject
+ * to Mode, Structure, and Type.
+ *
+ * N.B.: Form isn't handled.
+ */
+static int receive_data FUNCTION((instr, outstr), FILE *instr AND FILE *outstr)
+{
+ register int c;
+ int cnt, bare_lfs = 0;
+ char buf[BUFSIZ];
+
+ transflag++;
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ return (-1);
+ }
+ switch (type) {
+
+ case TYPE_I:
+ case TYPE_L:
+ while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) {
+ if (write(fileno(outstr), buf, cnt) != cnt)
+ goto file_err;
+ byte_count += cnt;
+ }
+ if (cnt < 0)
+ goto data_err;
+ transflag = 0;
+ return (0);
+
+ case TYPE_E:
+ reply(553, "TYPE E not implemented.");
+ transflag = 0;
+ return (-1);
+
+ case TYPE_A:
+ while ((c = getc(instr)) != EOF) {
+ byte_count++;
+ if (c == '\n')
+ bare_lfs++;
+ while (c == '\r') {
+ if (ferror(outstr))
+ goto data_err;
+ if ((c = getc(instr)) != '\n') {
+ putc('\r', outstr);
+ if (c == '\0' || c == EOF)
+ goto contin2;
+ }
+ }
+ putc(c, outstr);
+ contin2:;
+ }
+ fflush(outstr);
+ if (ferror(instr))
+ goto data_err;
+ if (ferror(outstr))
+ goto file_err;
+ transflag = 0;
+ if (bare_lfs) {
+ lreply(230, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs);
+ printf(" File may not have transferred correctly.\r\n");
+ }
+ return (0);
+ default:
+ reply(550, "Unimplemented TYPE %d in receive_data", type);
+ transflag = 0;
+ return (-1);
+ }
+
+data_err:
+ transflag = 0;
+ perror_reply(426, "Data Connection");
+ return (-1);
+
+file_err:
+ transflag = 0;
+ perror_reply(452, "Error writing file");
+ return (-1);
+}
+
+VOIDRET statfilecmd FUNCTION((filename), char *filename)
+{
+ char line[BUFSIZ];
+ FILE *fin;
+ int c;
+
+#if HAVE_LS_G_FLAG
+ sprintf(line, "%s %s", "/bin/ls -lgA", filename);
+#else /* HAVE_LS_G_FLAG */
+ sprintf(line, "%s %s", "/bin/ls -lA", filename);
+#endif /* HAVE_LS_G_FLAG */
+ fin = ftpd_popen(line, "r");
+ lreply(211, "status of %s:", filename);
+ while ((c = getc(fin)) != EOF) {
+ if (c == '\n') {
+ if (ferror(stdout)) {
+ perror_reply(421, "control connection");
+ ftpd_pclose(fin);
+ dologout(1);
+ /* NOTREACHED */
+ }
+ if (ferror(fin)) {
+ perror_reply(551, filename);
+ ftpd_pclose(fin);
+ return;
+ }
+ putc('\r', stdout);
+ }
+ putc(c, stdout);
+ }
+ ftpd_pclose(fin);
+ reply(211, "End of Status");
+}
+
+VOIDRET statcmd FUNCTION_NOARGS
+{
+/* COMMENTED OUT STUFF BECAUSE THINGS BROKE ON SUNOS. */
+ struct sockaddr_in *sin;
+ u_char *a, *p;
+
+ lreply(211, "FTP server status:");
+ printf(" \r\n");
+ printf(" Connected to %s", remotehost);
+ if (!isdigit(remotehost[0]))
+ printf(" (%s)", inet_ntoa(his_addr.sin_addr));
+ printf("\r\n");
+ if (logged_in) {
+#if DOANONYMOUS
+ if (guest)
+ printf(" Logged in anonymously\r\n");
+ else
+#endif /* DOANONYMOUS */
+ printf(" Logged in as %s\r\n", pw->pw_name);
+ } else
+ if (askpasswd)
+ printf(" Waiting for password\r\n");
+ else
+ printf(" Waiting for user name\r\n");
+ if (data != -1)
+ printf(" Data connection open\r\n");
+ else
+ if (pdata != -1) {
+ printf(" in Passive mode");
+ sin = &pasv_addr;
+ goto printaddr;
+ } else
+ if (usedefault == 0) {
+ printf(" PORT");
+ sin = &data_dest;
+ printaddr:
+ a = (u_char *) & sin->sin_addr;
+ p = (u_char *) & sin->sin_port;
+#define UC(b) (((int) b) & 0xff)
+ printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
+ UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+#undef UC
+ } else
+ printf(" No data connection\r\n");
+ reply(211, "End of status");
+}
+
+VOIDRET opiefatal FUNCTION((s), char *s)
+{
+ reply(451, "Error in server: %s\n", s);
+ reply(221, "Closing connection due to server error.");
+ dologout(0);
+ /* NOTREACHED */
+}
+
+static VOIDRET ack FUNCTION((s), char *s)
+{
+ reply(250, "%s command successful.", s);
+}
+
+VOIDRET nack FUNCTION((s), char *s)
+{
+ reply(502, "%s command not implemented.", s);
+}
+
+VOIDRET yyerror FUNCTION((s), char *s)
+{
+ char *cp;
+
+ if (cp = strchr(cbuf, '\n'))
+ *cp = '\0';
+ reply(500, "'%s': command not understood.", cbuf);
+}
+
+VOIDRET delete FUNCTION((name), char *name)
+{
+ struct stat st;
+
+ if (stat(name, &st) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+ if ((st.st_mode & S_IFMT) == S_IFDIR) {
+ if (rmdir(name) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+ goto done;
+ }
+ if (unlink(name) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+done:
+ ack("DELE");
+}
+
+VOIDRET cwd FUNCTION((path), char *path)
+{
+ if (chdir(path) < 0)
+ perror_reply(550, path);
+ else
+ ack("CWD");
+}
+
+VOIDRET makedir FUNCTION((name), char *name)
+{
+ if (mkdir(name, 0777) < 0)
+ perror_reply(550, name);
+ else
+ reply(257, "MKD command successful.");
+}
+
+VOIDRET removedir FUNCTION((name), char *name)
+{
+ if (rmdir(name) < 0)
+ perror_reply(550, name);
+ else
+ ack("RMD");
+}
+
+VOIDRET pwd FUNCTION_NOARGS
+{
+ char path[MAXPATHLEN + 1];
+
+ if (getcwd(path, MAXPATHLEN) == (char *) NULL)
+ reply(550, "%s.", path);
+ else
+ reply(257, "\"%s\" is current directory.", path);
+}
+
+char *renamefrom FUNCTION((name), char *name)
+{
+ struct stat st;
+
+ if (stat(name, &st) < 0) {
+ perror_reply(550, name);
+ return ((char *) 0);
+ }
+ reply(350, "File exists, ready for destination name");
+ return (name);
+}
+
+VOIDRET renamecmd FUNCTION((from, to), char *from AND char *to)
+{
+ if (rename(from, to) < 0)
+ perror_reply(550, "rename");
+ else
+ ack("RNTO");
+}
+
+static VOIDRET dolog FUNCTION((sin), struct sockaddr_in *sin)
+{
+ struct hostent *hp = gethostbyaddr((char *) &sin->sin_addr,
+ sizeof(struct in_addr), AF_INET);
+ time_t t, time();
+
+ if (hp)
+ strncpy(remotehost, hp->h_name, sizeof(remotehost));
+ else
+ strncpy(remotehost, inet_ntoa(sin->sin_addr), sizeof(remotehost));
+#if DOTITLE
+ sprintf(proctitle, "%s: connected", remotehost);
+ setproctitle(proctitle);
+#endif /* DOTITLE */
+
+ t = time((time_t *) 0);
+ syslog(LOG_INFO, "connection from %s at %s",
+ remotehost, ctime(&t));
+}
+
+/*
+ * Record logout in wtmp file
+ * and exit with supplied status.
+ */
+VOIDRET dologout FUNCTION((status), int status)
+{
+ if (logged_in) {
+ if (seteuid((uid_t) 0))
+ syslog(LOG_ERR, "Can't set euid");
+ logwtmp(ttyline, "", "");
+ }
+ /* beware of flushing buffers after a SIGPIPE */
+ _exit(status);
+}
+
+static VOIDRET myoob FUNCTION((input), int input)
+{
+ char *cp;
+
+ /* only process if transfer occurring */
+ if (!transflag)
+ return;
+ cp = tmpline;
+ if (getline(cp, 7, stdin) == NULL) {
+ reply(221, "You could at least say goodbye.");
+ dologout(0);
+ }
+ upper(cp);
+ if (strcmp(cp, "ABOR\r\n") == 0) {
+ tmpline[0] = '\0';
+ reply(426, "Transfer aborted. Data connection closed.");
+ reply(226, "Abort successful");
+ longjmp(urgcatch, 1);
+ }
+ if (strcmp(cp, "STAT\r\n") == 0) {
+ if (file_size != (off_t) - 1)
+ reply(213, "Status: %lu of %lu bytes transferred",
+ byte_count, file_size);
+ else
+ reply(213, "Status: %lu bytes transferred", byte_count);
+ }
+}
+
+/*
+ * Note: a response of 425 is not mentioned as a possible response to
+ * the PASV command in RFC959. However, it has been blessed as
+ * a legitimate response by Jon Postel in a telephone conversation
+ * with Rick Adams on 25 Jan 89.
+ */
+VOIDRET passive FUNCTION_NOARGS
+{
+ int len;
+ register char *p, *a;
+
+ pdata = socket(AF_INET, SOCK_STREAM, 0);
+ if (pdata < 0) {
+ perror_reply(425, "Can't open passive connection");
+ return;
+ }
+ pasv_addr = ctrl_addr;
+ pasv_addr.sin_port = 0;
+ if (seteuid((uid_t) 0))
+ syslog(LOG_ERR, "Can't set euid");
+ if (bind(pdata, (struct sockaddr *) & pasv_addr, sizeof(pasv_addr)) < 0) {
+ seteuid((uid_t) pw->pw_uid);
+ goto pasv_error;
+ }
+ if (seteuid((uid_t) pw->pw_uid))
+ syslog(LOG_ERR, "Can't set euid");
+ len = sizeof(pasv_addr);
+ if (getsockname(pdata, (struct sockaddr *) & pasv_addr, &len) < 0)
+ goto pasv_error;
+ if (listen(pdata, 1) < 0)
+ goto pasv_error;
+ a = (char *) &pasv_addr.sin_addr;
+ p = (char *) &pasv_addr.sin_port;
+
+#define UC(b) (((int) b) & 0xff)
+
+ reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
+ UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+ return;
+
+pasv_error:
+ close(pdata);
+ pdata = -1;
+ perror_reply(425, "Can't open passive connection");
+ return;
+}
+
+/*
+ * Generate unique name for file with basename "local".
+ * The file named "local" is already known to exist.
+ * Generates failure reply on error.
+ */
+static char *gunique FUNCTION((local), char *local)
+{
+ static char new[MAXPATHLEN];
+ struct stat st;
+ char *cp = strrchr(local, '/');
+ int count = 0;
+
+ if (cp)
+ *cp = '\0';
+ if (stat(cp ? local : ".", &st) < 0) {
+ perror_reply(553, cp ? local : ".");
+ return ((char *) 0);
+ }
+ if (cp)
+ *cp = '/';
+ strcpy(new, local);
+ cp = new + strlen(new);
+ *cp++ = '.';
+ for (count = 1; count < 100; count++) {
+ sprintf(cp, "%d", count);
+ if (stat(new, &st) < 0)
+ return (new);
+ }
+ reply(452, "Unique file name cannot be created.");
+ return ((char *) 0);
+}
+
+/*
+ * Format and send reply containing system error number.
+ */
+VOIDRET perror_reply FUNCTION((code, string), int code AND char *string)
+{
+ reply(code, "%s: %s.", string, strerror(errno));
+}
+
+static char *onefile[] =
+{
+ "",
+ 0
+};
+
+VOIDRET send_file_list FUNCTION((whichfiles), char *whichfiles)
+{
+ struct stat st;
+ DIR *dirp = NULL;
+ struct dirent *dir;
+ FILE *dout = NULL;
+ register char **dirlist, *dirname;
+ int simple = 0;
+
+ if (strpbrk(whichfiles, "~{[*?") != NULL) {
+ extern char **ftpglob(), *globerr;
+
+ globerr = NULL;
+ dirlist = ftpglob(whichfiles);
+ if (globerr != NULL) {
+ reply(550, globerr);
+ return;
+ } else
+ if (dirlist == NULL) {
+ errno = ENOENT;
+ perror_reply(550, whichfiles);
+ return;
+ }
+ } else {
+ onefile[0] = whichfiles;
+ dirlist = onefile;
+ simple = 1;
+ }
+
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ return;
+ }
+ while (dirname = *dirlist++) {
+ if (stat(dirname, &st) < 0) {
+ /* If user typed "ls -l", etc, and the client used NLST, do what the
+ user meant. */
+ if (dirname[0] == '-' && *dirlist == NULL &&
+ transflag == 0) {
+ retrieve("/bin/ls %s", dirname);
+ return;
+ }
+ perror_reply(550, whichfiles);
+ if (dout != NULL) {
+ fclose(dout);
+ transflag = 0;
+ data = -1;
+ pdata = -1;
+ }
+ return;
+ }
+ if ((st.st_mode & S_IFMT) == S_IFREG) {
+ if (dout == NULL) {
+ dout = dataconn("file list", (off_t) - 1, "w");
+ if (dout == NULL)
+ return;
+ transflag++;
+ }
+ fprintf(dout, "%s%s\n", dirname,
+ type == TYPE_A ? "\r" : "");
+ byte_count += strlen(dirname) + 1;
+ continue;
+ } else
+ if ((st.st_mode & S_IFMT) != S_IFDIR)
+ continue;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ continue;
+
+ while ((dir = readdir(dirp)) != NULL) {
+ char nbuf[MAXPATHLEN];
+
+ if (dir->d_name[0] == '.' && (strlen(dir->d_name) == 1))
+ continue;
+ if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
+ (strlen(dir->d_name) == 2))
+ continue;
+
+ sprintf(nbuf, "%s/%s", dirname, dir->d_name);
+
+ /* We have to do a stat to insure it's not a directory or special file. */
+ if (simple || (stat(nbuf, &st) == 0 &&
+ (st.st_mode & S_IFMT) == S_IFREG)) {
+ if (dout == NULL) {
+ dout = dataconn("file list", (off_t) - 1, "w");
+ if (dout == NULL)
+ return;
+ transflag++;
+ }
+ if (nbuf[0] == '.' && nbuf[1] == '/')
+ fprintf(dout, "%s%s\n", &nbuf[2],
+ type == TYPE_A ? "\r" : "");
+ else
+ fprintf(dout, "%s%s\n", nbuf,
+ type == TYPE_A ? "\r" : "");
+ byte_count += strlen(nbuf) + 1;
+ }
+ }
+ closedir(dirp);
+ }
+
+ if (dout == NULL)
+ reply(550, "No files found.");
+ else
+ if (ferror(dout) != 0)
+ perror_reply(550, "Data connection");
+ else
+ reply(226, "Transfer complete.");
+
+ transflag = 0;
+ if (dout != NULL)
+ fclose(dout);
+ data = -1;
+ pdata = -1;
+}
+
+#if DOTITLE
+/*
+ * clobber argv so ps will show what we're doing.
+ * (stolen from sendmail)
+ * warning, since this is usually started from inetd.conf, it
+ * often doesn't have much of an environment or arglist to overwrite.
+ */
+VOIDRET setproctitle FUNCTION((fmt, a, b, c), char *fmt AND int a AND int b AND int c)
+{
+ register char *p, *bp, ch;
+ register int i;
+ char buf[BUFSIZ];
+
+ sprintf(buf, fmt, a, b, c);
+
+ /* make ps print our process name */
+ p = Argv[0];
+ *p++ = '-';
+
+ i = strlen(buf);
+ if (i > LastArgv - p - 2) {
+ i = LastArgv - p - 2;
+ buf[i] = '\0';
+ }
+ bp = buf;
+ while (ch = *bp++)
+ if (ch != '\n' && ch != '\r')
+ *p++ = ch;
+ while (p < LastArgv)
+ *p++ = ' ';
+}
+#endif /* DOTITLE */
+
+void catchexit FUNCTION_NOARGS
+{
+ closelog();
+}
+
+int main FUNCTION((argc, argv, envp), int argc AND char *argv[] AND char *envp[])
+{
+ int addrlen, on = 1;
+ char *cp;
+#ifdef IP_TOS
+ int tos;
+#endif /* IP_TOS */
+
+ {
+ int i;
+
+ for (i = sysconf(_SC_OPEN_MAX); i > 2; i--)
+ close(i);
+ }
+
+ /* LOG_NDELAY sets up the logging connection immediately, necessary for
+ anonymous ftp's that chroot and can't do it later. */
+ openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
+ atexit(catchexit);
+ addrlen = sizeof(his_addr);
+ if (getpeername(0, (struct sockaddr *) & his_addr, &addrlen) < 0) {
+ syslog(LOG_ERR, "getpeername (%s): %m", argv[0]);
+ exit(1);
+ }
+ addrlen = sizeof(ctrl_addr);
+ if (getsockname(0, (struct sockaddr *) & ctrl_addr, &addrlen) < 0) {
+ syslog(LOG_ERR, "getsockname (%s): %m", argv[0]);
+ exit(1);
+ }
+#ifdef IP_TOS
+ tos = IPTOS_LOWDELAY;
+ if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0)
+ syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+ data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
+ debug = 0;
+#if DOTITLE
+ /* Save start and extent of argv for setproctitle. */
+ Argv = argv;
+ while (*envp)
+ envp++;
+ LastArgv = envp[-1] + strlen(envp[-1]);
+#endif /* DOTITLE */
+
+ argc--, argv++;
+ while (argc > 0 && *argv[0] == '-') {
+ for (cp = &argv[0][1]; *cp; cp++)
+ switch (*cp) {
+
+ case 'v':
+ debug = 1;
+ break;
+
+ case 'd':
+ debug = 1;
+ break;
+
+ case 'l':
+ break;
+
+ case 't':
+ timeout = atoi(++cp);
+ if (maxtimeout < timeout)
+ maxtimeout = timeout;
+ goto nextopt;
+
+ case 'T':
+ maxtimeout = atoi(++cp);
+ if (timeout > maxtimeout)
+ timeout = maxtimeout;
+ goto nextopt;
+
+ case 'u':
+ {
+ int val = 0;
+
+ while (*++cp && *cp >= '0' && *cp <= '9')
+ val = val * 8 + *cp - '0';
+ if (*cp)
+ fprintf(stderr, "ftpd: Bad value for -u\n");
+ else
+ defumask = val;
+ goto nextopt;
+ }
+
+ default:
+ fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n",
+ *cp);
+ break;
+ }
+nextopt:
+ argc--, argv++;
+ }
+ freopen(_PATH_DEVNULL, "w", stderr);
+ signal(SIGPIPE, lostconn);
+ signal(SIGCHLD, SIG_IGN);
+ if ((int) signal(SIGURG, myoob) < 0)
+ syslog(LOG_ERR, "signal: %m");
+
+ /* Try to handle urgent data inline */
+#ifdef SO_OOBINLINE
+ if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof(on)) < 0)
+ syslog(LOG_ERR, "setsockopt: %m");
+#endif
+
+#ifdef F_SETOWN
+ if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
+ syslog(LOG_ERR, "fcntl F_SETOWN: %m");
+#endif
+ dolog(&his_addr);
+ /* Set up default state */
+ data = -1;
+ type = TYPE_A;
+ form = FORM_N;
+ stru = STRU_F;
+ mode = MODE_S;
+ tmpline[0] = '\0';
+ af_pwok = opieaccessfile(remotehost);
+
+#if 0
+ {
+ struct utsname utsname;
+
+ if (uname(&utsname) < 0) {
+ syslog(LOG_ERR, "uname() failed: %s", strerror(errno));
+ exit(1);
+ }
+
+ reply(220, "%s FTP server ready.", utsname.nodename);
+ }
+#else /* 0 */
+ reply(220, "FTP server ready.");
+#endif /* 0 */
+
+ setjmp(errcatch);
+ for (;;)
+ yyparse();
+ /* NOTREACHED */
+ return 0;
+}
diff --git a/contrib/opie/opiegen.1 b/contrib/opie/opiegen.1
new file mode 100644
index 0000000..7dc1dfd
--- /dev/null
+++ b/contrib/opie/opiegen.1
@@ -0,0 +1,88 @@
+.\" opiegen.1: Manual page for the opiegen(1) program.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Created by cmetz for OPIE 2.2 from opiekey.1.
+.\"
+.ll 6i
+.pl 10.5i
+.lt 6.0i
+.TH OPIEKEY 1 "February 20, 1996"
+.AT 3
+.SH NAME
+opiegen \- Example OPIE-based OTP generator
+
+.SH SYNOPSIS
+.B opiegen
+.sp 0
+[
+.I challenge
+]
+.sp 0
+
+.SH DESCRIPTION
+.I opiegen
+takes a properly formed OTP challenge either from the command line or from
+standard input, prompts the user for a secret pass phrase, and generates an
+OTP response to that challenge. It is intended as an example for programmers
+of how a simple OTP generator can be built. Users should probably use the
+.I opiekey
+program instead.
+
+.SH EXAMPLE
+.sp 0
+wintermute$ opiegen otp-md5 495 wi01309
+.sp 0
+Secret Pass Phrase:
+.sp 0
+GILL HUED GOES CHUM LIEU VAIN
+.sp 0
+wintermute$
+.LP
+
+.SH BUGS
+.BR opiegen(1)
+can lull a user into revealing his/her password when remotely logged in, thus
+defeating the purpose of OPIE. This is especially a problem with xterm.
+.BR opiegen(1) implements simple checks to reduce the risk of a user making
+this mistake. Better checks are needed.
+.LP
+
+.SH SEE ALSO
+.BR opiekey (1),
+.BR opieserv (1),
+.BR opie (4),
+.BR opiepasswd (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8),
+.BR opiekeys (5),
+.BR opieaccess (5)
+
+.SH AUTHOR
+The opiegen(1) program was created by Craig Metz for OPIE 2.2.
+
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opiegen.c b/contrib/opie/opiegen.c
new file mode 100644
index 0000000..7f1ff34
--- /dev/null
+++ b/contrib/opie/opiegen.c
@@ -0,0 +1,88 @@
+/* opiegen.c: Sample OTP generator based on the opiegenerator()
+ library routine.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. OPIE_PASS_MAX changed to
+ OPIE_SECRET_MAX. Send debug info to syslog.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION definition et al.
+ Fixed include order.
+ Created at NRL for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#include <stdio.h>
+#if DEBUG
+#include <syslog.h>
+#endif /* DEBUG */
+#include "opie.h"
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ char buffer[OPIE_CHALLENGE_MAX+1];
+ char secret[OPIE_SECRET_MAX+1];
+ char response[OPIE_RESPONSE_MAX+1];
+ int result;
+
+ if (opieinsecure()) {
+ fputs("Sorry, but you don't seem to be on a secure terminal.\n", stderr);
+#if !DEBUG
+ exit(1);
+#endif /* !DEBUG */
+ }
+
+ if (argc <= 1) {
+ fputs("Challenge: ", stderr);
+ if (!opiereadpass(buffer, sizeof(buffer)-1, 1))
+ fprintf(stderr, "Error reading challenge!");
+ } else {
+ char *ap, *ep, *c;
+ int i;
+
+ ep = buffer + sizeof(buffer) - 1;
+ for (i = 1, ap = buffer; (i < argc) && (ap < ep); i++) {
+ c = argv[i];
+ while ((*(ap++) = *(c++)) && (ap < ep));
+ *(ap - 1) = ' ';
+ }
+ *(ap - 1) = 0;
+#if DEBUG
+ syslog(LOG_DEBUG, "opiegen: challenge is +%s+\n", buffer);
+#endif /* DEBUG */
+ }
+ buffer[sizeof(buffer)-1] = 0;
+
+ fputs("Secret pass phrase: ", stderr);
+ if (!opiereadpass(secret, OPIE_SECRET_MAX, 0)) {
+ fputs("Error reading secret pass phrase!\n", stderr);
+ exit(1);
+ };
+
+ switch (result = opiegenerator(buffer, secret, response)) {
+ case -2:
+ fputs("Not a valid OTP secret pass phrase.\n", stderr);
+ break;
+ case -1:
+ fputs("Error processing challenge!\n", stderr);
+ break;
+ case 1:
+ fputs("Not a valid OTP challenge.\n", stderr);
+ break;
+ case 0:
+ fputs(response, stdout);
+ fputc('\n', stdout);
+ fflush(stdout);
+ memset(secret, 0, sizeof(secret));
+ exit(0);
+ default:
+ fprintf(stderr, "Unknown error %d!\n", result);
+ }
+ memset(secret, 0, sizeof(secret));
+ return 1;
+}
diff --git a/contrib/opie/opieinfo.1 b/contrib/opie/opieinfo.1
new file mode 100644
index 0000000..c8d08f8
--- /dev/null
+++ b/contrib/opie/opieinfo.1
@@ -0,0 +1,99 @@
+.\" opieinfo.1: Manual page for the opieinfo(1) program.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation.
+.\" Modified at NRL for OPIE 2.0.
+.\" Written at Bellcore for the S/Key Version 1 software distribution
+.\" (keyinfo.1).
+.\"
+.ll 6i
+.pl 10.5i
+.lt 6.0i
+.TH OPIEINFO 1 "January 10, 1995"
+.AT 3
+.SH NAME
+opieinfo \- Extract sequence number and seed for future OPIE challenges.
+
+.SH SYNOPSIS
+.B opieinfo
+[\-v] [\-h] [
+.I user_name
+]
+
+.SH DESCRIPTION
+.I opieinfo
+takes an optional user name and writes the current sequence number
+and seed found in the OPIE key database for either the current user
+or the user specified. opiekey is compatible with the
+.IR keyinfo (1)
+program
+from Bellcore's S/Key Version 1 except that specification of a remote
+system name is not permitted.
+.sp
+.I opieinfo
+can be used to generate a listing of your future OPIE responses
+if you are going to be without an OPIE calculator and still need to log into
+the system. To do so, you would run something like:
+.sp
+.B opiekey \-n 42 `opieinfo`
+
+.SH OPTIONS
+.TP
+.B \-v
+Display the version number and compile-time options, then exit.
+.TP
+.B \-h
+Display a brief help message and exit.
+.TP
+.B <user_name>
+The name of a user whose key information you wish to display. The default is
+the user running opieinfo.
+
+.SH EXAMPLE
+.sp 0
+wintermute$ opieinfo
+.sp 0
+495 wi01309
+.sp 0
+wintermute$
+.LP
+
+.SH FILES
+.TP
+/etc/opiekeys -- database of key information for the OPIE system.
+
+.SH SEE ALSO
+.BR opie (4),
+.BR opiekey (1),
+.BR opiepasswd (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8),
+.BR opiekeys (5)
+.BR opieaccess (5)
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opieinfo.c b/contrib/opie/opieinfo.c
new file mode 100644
index 0000000..f1b0acb
--- /dev/null
+++ b/contrib/opie/opieinfo.c
@@ -0,0 +1,90 @@
+/*
+opieinfo: Print a user's current OPIE sequence number and seed
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Removed unneeded debug message.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION definition et al.
+ Fixed include order. Make everything static. Ifdef around
+ some headers.
+ Modified at NRL for OPIE 2.1. Substitute @@KEY_FILE@@. Re-write in
+ C.
+ Modified at NRL for OPIE 2.01. Remove hard-coded paths for grep and
+ awk and let PATH take care of it. Substitute for Makefile
+ variables $(EXISTS) and $(KEY_FILE). Only compute $WHO if
+ there's a key file. Got rid of grep since awk can do the job
+ itself.
+ Modified at NRL for OPIE 2.0.
+ Written at Bellcore for the S/Key Version 1 software distribution
+ (keyinfo)
+*/
+
+#include "opie_cfg.h"
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif /* HAVE_PWD_H */
+#include "opie.h"
+
+/* extern char *optarg; */
+extern int errno, optind;
+
+static char *getusername FUNCTION_NOARGS
+{
+ struct passwd *p = getpwuid(getuid());
+
+ if (!p)
+ return getlogin();
+
+ return p->pw_name;
+}
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ char *username;
+ struct opie opie;
+ int i;
+
+ while ((i = getopt(argc, argv, "hv")) != EOF) {
+ switch (i) {
+ case 'v':
+ opieversion();
+ case 'h':
+ default:
+ fprintf(stderr, "usage: %s [-h] [-v] [user_name]\n", argv[0]);
+ exit(0);
+ }
+ }
+
+ if (optind < argc)
+ username = argv[optind];
+ else
+ username = getusername();
+
+ if ((i = opielookup(&opie, username)) && (i != 2)) {
+ if (i < 0)
+ fprintf(stderr, "Error opening database! (errno = %d)\n", errno);
+ else
+ fprintf(stderr, "%s not found in database.\n", username);
+ exit(1);
+ }
+
+ printf("%d %s\n", opie.opie_n - 1, opie.opie_seed);
+
+ return 0;
+}
diff --git a/contrib/opie/opiekey.1 b/contrib/opie/opiekey.1
new file mode 100644
index 0000000..74fc8ca
--- /dev/null
+++ b/contrib/opie/opiekey.1
@@ -0,0 +1,173 @@
+.\" opiekey.1: Manual page for the opiekey(1) program.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Modified by cmetz for OPIE 2.3. Added -t documentation. Removed
+.\" opie-bugs pointer. Removed opie-md5 and opie-md4 names. Fixed
+.\" a bolding bug. Added -f flag. Added escapes on flags. Minor
+.\" editorial changes. Updated example.
+.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation.
+.\" Re-worded retype documentation. Added opiegen reference.
+.\" Added -x documentation.
+.\" Modified at NRL for OPIE 2.0.
+.\" Written at Bellcore for the S/Key Version 1 software distribution
+.\" (key.1).
+.\"
+.ll 6i
+.pl 10.5i
+.lt 6.0i
+.TH OPIEKEY 1 "February 20, 1996"
+.AT 3
+.SH NAME
+opiekey, otp-md4, otp-md5 \- Programs for computing responses to OTP challenges.
+
+.SH SYNOPSIS
+.B opiekey
+|
+.B otp-md4
+|
+.B otp-md5
+[\-v] [\-h] [\-f] [\-x]
+.sp 0
+[\-t
+.I
+type
+] [\-4|\-5]
+[\-a] [\-n
+.I count
+]
+.I sequence_number seed
+.sp 0
+
+.SH DESCRIPTION
+.I opiekey
+takes the optional count of the number of responses to
+print along with a (maximum) sequence number and seed as command line
+args. It prompts for the user's secret pass phrase and produces an OPIE
+response as six words. If compiled to do so, it can prompt for the user's
+secret pass phrase twice to help reduce errors due to mistypes. The second
+password entry can be circumvented by entering only an end of line.
+.I opiekey
+is downward compatible with the
+.IR key (1)
+program from the Bellcore S/Key Version 1 distribution and several of its
+variants.
+
+.SH OPTIONS
+.TP
+.B \-v
+Display the version number and compile-time options, then exit.
+.TP
+.B \-h
+Display a brief help message and exit.
+.TP
+.B \-4, \-5
+Selects MD4 or MD5, respectively, as the response generation algorithm. The
+default for otp-md4 is MD4 and the default for opie-md5 is MD5. The default
+for opiekey depends on compile-time configuration, but should be MD5. MD4 is
+compatible with the Bellcore S/Key Version 1 distribution.
+.TP
+.B \-f
+Force
+.I opiekey
+to continue, even where it normally shouldn't. This is currently used to
+force opiekey to operate in even from terminals it believes to be insecure.
+It can also allow users to disclose their secret pass phrases to attackers.
+Use of the -f flag may be disabled by compile-time option in your particular
+build of OPIE.
+.TP
+.B \-a
+Allows you to input an arbitrary secret pass phrase, instead of running checks
+against it. Arbitrary currently does not include '\0' or '\n' characters. This
+can be used for backwards compatibility with key generators that do not check
+passwords.
+.TP
+.B \-n <count>
+the number of one time access passwords to print.
+The default is one.
+.TP
+.B \-x
+Output the OTPs as hexadecimal numbers instead of six words.
+.TP
+.B \-t <type>
+Generate an extended response of the specified type. Supported types are:
+.sp 1
+word six-word
+.sp 0
+hex hexadecimal
+.sp 0
+init hexadecimal re-initialization
+.sp 0
+init-word six-word re-initialization
+.sp 1
+The re-initialization responses
+.I always
+generate the simple active attack protection.
+.TP
+.SH EXAMPLE
+.sp 0
+wintermute$ opiekey \-5 \-n 5 495 wi01309
+.sp 0
+Using MD5 algorithm to compute response.
+.sp 0
+Reminder: Don't use opiekey from telnet or dial-in sessions.
+.sp 0
+Enter secret pass phrase:
+.sp 0
+491: HOST VET FOWL SEEK IOWA YAP
+.sp 0
+492: JOB ARTS WERE FEAT TILE IBIS
+.sp 0
+493: TRUE BRED JOEL USER HALT EBEN
+.sp 0
+494: HOOD WED MOLT PAN FED RUBY
+.sp 0
+495: SUB YAW BILE GLEE OWE NOR
+.sp 0
+wintermute$
+.LP
+
+.SH BUGS
+.BR opiekey(1)
+can lull a user into revealing his/her password when remotely logged in, thus
+defeating the purpose of OPIE. This is especially a problem with xterm.
+.BR opiekey(1)
+implements simple checks to reduce the risk of a user making
+this mistake. Better checks are needed.
+.LP
+
+.SH SEE ALSO
+.BR opie (4),
+.BR opiepasswd (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8),
+.BR opiekeys (5),
+.BR opieaccess (5),
+.BR opiegen (1)
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opiekey.c b/contrib/opie/opiekey.c
new file mode 100644
index 0000000..17b5ab0
--- /dev/null
+++ b/contrib/opie/opiekey.c
@@ -0,0 +1,375 @@
+/* opiekey.c: Stand-alone program for computing responses to OTP challenges.
+
+ Takes a sequence number and seed (presumably from an OPIE challenge)
+ as command line arguments, prompts for the user's secret pass phrase,
+ and outputs a response.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. OPIE_PASS_MAX changed to
+ OPIE_SECRET_MAX. Added extended responses, which created
+ lots of changes. Eliminated extra variable. Added -x and
+ -t to help. Added -f flag. Added SHA support.
+ Modified by cmetz for OPIE 2.22. Print newline after seed too long
+ message. Check for minimum seed length. Correct a grammar
+ error.
+ Modified at NRL for OPIE 2.2. Check opiereadpass() return.
+ Change opiereadpass() calls to add echo arg. Use FUNCTION
+ definition et al. Check seed length here, too. Added back
+ hex output. Reworked final output function.
+ Modified at NRL for OPIE 2.0.
+ Written at Bellcore for the S/Key Version 1 software distribution
+ (skey.c).
+*/
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "opie.h"
+
+#ifdef __MSDOS__
+#include <dos.h>
+#endif
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
+
+extern char *optarg;
+extern int optind, opterr;
+
+int aflag = 0;
+
+char *algnames[] = { NULL, NULL, NULL, "SHA-1", "MD4", "MD5" };
+char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
+
+/******** Begin real source code ***************/
+
+static VOIDRET usage FUNCTION((s), char *s)
+{
+ fprintf(stderr, "usage: %s [-v] [-h] [-f] [-x] [-t type] [-4 | -5 | -s] [-a] [-n count] sequence_number seed\n", s);
+ exit(1);
+}
+
+#define RESPONSE_STANDARD 0
+#define RESPONSE_WORD 1
+#define RESPONSE_HEX 2
+#define RESPONSE_INIT 3
+#define RESPONSE_INIT_WORD 4
+#define RESPONSE_UNKNOWN 5
+
+struct _rtrans {
+ int type;
+ char *name;
+};
+
+static struct _rtrans rtrans[] = {
+ { RESPONSE_WORD, "word" },
+ { RESPONSE_HEX, "hex" },
+ { RESPONSE_INIT, "init" },
+ { RESPONSE_INIT_WORD, "init-word" },
+ { RESPONSE_STANDARD, "" },
+ { RESPONSE_STANDARD, "standard" },
+ { RESPONSE_STANDARD, "otp" },
+ { RESPONSE_UNKNOWN, NULL }
+};
+
+static void getsecret FUNCTION((secret, promptextra, retype), char *secret AND char *promptextra AND int flags)
+{
+ fprintf(stderr, "Enter %ssecret pass phrase: ", promptextra);
+ if (!opiereadpass(secret, OPIE_SECRET_MAX, 0)) {
+ fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra);
+ exit(1);
+ }
+ if (secret[0] && (flags & 1)) {
+ char verify[OPIE_SECRET_MAX + 1];
+
+ fprintf(stderr, "Again %ssecret pass phrase: ", promptextra);
+ if (!opiereadpass(verify, OPIE_SECRET_MAX, 0)) {
+ fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra);
+ memset(verify, 0, sizeof(verify));
+ memset(secret, 0, sizeof(secret));
+ exit(1);
+ }
+ if (verify[0] && strcmp(verify, secret)) {
+ fprintf(stderr, "They don't match. Try again.\n");
+ memset(verify, 0, sizeof(verify));
+ memset(secret, 0, sizeof(secret));
+ exit(1);
+ }
+ memset(verify, 0, sizeof(verify));
+ }
+ if (!(flags & 2) && opiepasscheck(secret)) {
+ memset(secret, 0, sizeof(secret));
+ fprintf(stderr, "Secret pass phrases must be between %d and %d characters long.\n", OPIE_SECRET_MIN, OPIE_SECRET_MAX);
+ exit(1);
+ };
+}
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ /* variable declarations */
+ unsigned algorithm = MDX; /* default algorithm per Makefile's MDX
+ symbol */
+ int keynum = 0;
+ int i;
+ int count = 1;
+ char secret[OPIE_SECRET_MAX + 1], newsecret[OPIE_SECRET_MAX + 1];
+ char key[8], newkey[8];
+ char cko[8], ckn[8], ckxor[8], cv[8];
+ char *seed, newseed[OPIE_SEED_MAX + 1];
+ char response[OPIE_RESPONSE_MAX + 1];
+ char *slash;
+ int hex = 0;
+ int type = RESPONSE_STANDARD;
+ int force;
+
+ if (slash = strchr(argv[0], '/'))
+ slash++;
+ else
+ slash = argv[0];
+
+ if (!strcmp(slash, "key") || strstr(slash, "md4"))
+ algorithm = 4;
+
+ if (strstr(slash, "md5"))
+ algorithm = 5;
+
+ if (strstr(slash, "sha"))
+ algorithm = 3;
+
+ while ((i = getopt(argc, argv, "fhvn:x45at:s")) != EOF) {
+ switch (i) {
+ case 'v':
+ opieversion();
+
+ case 'n':
+ count = atoi(optarg);
+ break;
+
+ case 'x':
+ hex = 1;
+ break;
+
+ case 'f':
+#if INSECURE_OVERRIDE
+ force = 1;
+#else /* INSECURE_OVERRIDE */
+ fprintf(stderr, "Sorry, but the -f option is not supported by this build of OPIE.\n");
+#endif /* INSECURE_OVERRIDE */
+ break;
+
+ case '4':
+ /* use MD4 algorithm */
+ algorithm = 4;
+ break;
+
+ case '5':
+ /* use MD5 algorithm */
+ algorithm = 5;
+ break;
+
+ case 'a':
+ aflag = 1;
+ break;
+
+ case 't':
+ {
+ struct _rtrans *r;
+ for (r = rtrans; r->name && strcmp(r->name, optarg); r++);
+ if (!r->name) {
+ fprintf(stderr, "%s: %s: unknown response type.\n", argv[0], optarg);
+ exit(1);
+ }
+ type = r->type;
+ }
+ break;
+
+ case 's':
+ algorithm = 3;
+ break;
+
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if ((argc - optind) < 2)
+ usage(argv[0]);
+
+ fprintf(stderr, "Using the %s algorithm to compute response.\n", algnames[algorithm]);
+
+ /* get sequence number, which is next-to-last parameter */
+ keynum = atoi(argv[optind]);
+ if (keynum < 1) {
+ fprintf(stderr, "Sequence number %s is not positive.\n", argv[optind]);
+ exit(1);
+ }
+ /* get seed string, which is last parameter */
+ seed = argv[optind + 1];
+ {
+ i = strlen(seed);
+
+ if (i > OPIE_SEED_MAX) {
+ fprintf(stderr, "Seeds must be less than %d characters long.\n", OPIE_SEED_MAX);
+ exit(1);
+ }
+ if (i < OPIE_SEED_MIN) {
+ fprintf(stderr, "Seeds must be greater than %d characters long.\n", OPIE_SEED_MIN);
+ exit(1);
+ }
+ }
+
+ fprintf(stderr, "Reminder: Don't use opiekey from telnet or dial-in sessions.\n");
+
+ if (opieinsecure()) {
+ fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n");
+#if INSECURE_OVERRIDE
+ if (force)
+ fprintf(stderr, "Warning: Continuing could disclose your secret pass phrase to an attacker!\n");
+ else
+#endif /* INSECURE_OVERRIDE */
+ exit(1);
+ }
+
+ if ((type == RESPONSE_INIT) || (type == RESPONSE_INIT_WORD)) {
+#if RETYPE
+ getsecret(secret, "old ", 1);
+#else /* RETYPE */
+ getsecret(secret, "old ", 0);
+#endif /* RETYPE */
+ getsecret(newsecret, "new ", 1);
+ if (!newsecret[0])
+ strcpy(newsecret, secret);
+
+ if (opienewseed(strcpy(newseed, seed)) < 0) {
+ fprintf(stderr, "Error updating seed.\n");
+ goto error;
+ }
+
+ if (opiekeycrunch(algorithm, newkey, newseed, newsecret)) {
+ fprintf(stderr, "%s: key crunch failed (1)\n", argv[0]);
+ goto error;
+ }
+
+ for (i = 0; i < 499; i++)
+ opiehash(newkey, algorithm);
+
+ if (opiekeycrunch(algorithm | 0x10, cko, seed, secret)) {
+ fprintf(stderr, "%s: key crunch failed (2)\n", argv[0]);
+ goto error;
+ }
+
+ if (opiekeycrunch(algorithm | 0x10, ckn, newseed, newsecret)) {
+ fprintf(stderr, "%s: key crunch failed (3)\n", argv[0]);
+ goto error;
+ }
+
+ for (i = 0; i < 8; i++)
+ ckxor[i] = cko[i] ^ ckn[i];
+ } else
+#if RETYPE
+ getsecret(secret, "", 1);
+#else /* RETYPE */
+ getsecret(secret, "", 0);
+#endif /* RETYPE */
+
+ /* Crunch seed and secret password into starting key normally */
+ if (opiekeycrunch(algorithm, key, seed, secret)) {
+ fprintf(stderr, "%s: key crunch failed\n", argv[0]);
+ goto error;
+ }
+
+ for (i = 0; i <= (keynum - count); i++)
+ opiehash(key, algorithm);
+
+ {
+ char buf[OPIE_SEED_MAX + 48 + 1];
+ char *c;
+
+ for (; i <= keynum; i++) {
+ if (count > 1)
+ printf("%d: %s", i, (type == RESPONSE_STANDARD) ? "" : "\n");
+
+ switch(type) {
+ case RESPONSE_STANDARD:
+ if (hex)
+ opiebtoh(response, key);
+ else
+ opiebtoe(response, key);
+ break;
+ case RESPONSE_WORD:
+ strcpy(response, "word:");
+ strcat(response, opiebtoe(buf, key));
+ break;
+ case RESPONSE_HEX:
+ strcpy(response, "hex:");
+ strcat(response, opiebtoh(buf, key));
+ break;
+ case RESPONSE_INIT:
+ case RESPONSE_INIT_WORD:
+ if (type == RESPONSE_INIT) {
+ strcpy(response, "init:");
+ strcat(response, opiebtoh(buf, key));
+ sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed);
+ strcat(response, buf);
+ strcat(response, opiebtoh(buf, newkey));
+ strcat(response, ":");
+ strcat(response, opiebtoh(buf, ckxor));
+ strcat(response, ":");
+ } else {
+ strcpy(response, "init-word:");
+ strcat(response, opiebtoe(buf, key));
+ sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed);
+ strcat(response, buf);
+ strcat(response, opiebtoe(buf, newkey));
+ strcat(response, ":");
+ strcat(response, opiebtoe(buf, ckxor));
+ strcat(response, ":");
+ }
+
+ c = buf;
+ memcpy(c, cko, sizeof(cko)); c += sizeof(cko);
+ memcpy(c, key, sizeof(key)); c += sizeof(key);
+#ifdef HAVE_ANSISPRINTF
+ c += sprintf(c, "%s 499 %s", algids[algorithm], newseed);
+#else /* HAVE_ANSISPRINTF */
+ sprintf(c, "%s 499 %s", algids[algorithm], newseed);
+ while(*c) c++;
+#endif /* HAVE_ANSISPRINTF */
+ memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey);
+ memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor);
+ memcpy(c, cko, sizeof(cko)); c += sizeof(cko);
+ opiehashlen(algorithm, buf, cv, (unsigned int)c - (unsigned int)buf);
+
+ strcat(response, (type == RESPONSE_INIT) ? opiebtoh(buf, cv) : opiebtoe(buf, cv));
+ break;
+ }
+ puts(response);
+ opiehash(key, algorithm);
+ }
+ }
+
+ memset(secret, 0, sizeof(secret));
+ memset(newsecret, 0, sizeof(newsecret));
+ return 0;
+
+error:
+ memset(secret, 0, sizeof(secret));
+ memset(newsecret, 0, sizeof(newsecret));
+ return 1;
+}
diff --git a/contrib/opie/opiekeys.5 b/contrib/opie/opiekeys.5
new file mode 100644
index 0000000..c4ef5f4
--- /dev/null
+++ b/contrib/opie/opiekeys.5
@@ -0,0 +1,66 @@
+.\" opieaccess.5: Manual page describing the /etc/opiekeys file.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Written at NRL for OPIE 2.0.
+.\"
+.ll 6i
+.pl 10.5i
+.\" @(#)opiekeys.1 2.0 (NRL) 1/10/95
+.\"
+.lt 6.0i
+.TH OPIEKEYS 1 "January 10, 1995"
+.AT 3
+.SH NAME
+[/etc/]opiekeys \- OPIE database of user key information
+
+.SH DESCRIPTION
+The
+.I opiekeys
+file contains user information used by the OPIE software to authenticate
+users. The
+.I opiekeys
+file is backwards compatible with the S/Key
+.I /etc/skeykeys
+database file, but only if the hashing algorithm (MD4 and MD5) is the same
+between S/Key and OPIE (i.e., MD5 OPIE cannot use MD4 S/Key keys). The
+.I opiekeys
+file consists of six fields separated by spaces (tabs are properly
+interpreted, but spaces should be used instead) as follows:
+.PP
+.nf
+.ta \w' 'u
+Field Description
+name User's login name.
+sequence User's sequence number.
+seed User's seed.
+key User's last response (hex).
+date Last change date.
+time Last change time.
+.fi
+.SH SEE ALSO
+.BR opie (4),
+.BR opiekeys (5),
+.BR opiepasswd (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8)
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opielogin.1 b/contrib/opie/opielogin.1
new file mode 100644
index 0000000..0f687cc
--- /dev/null
+++ b/contrib/opie/opielogin.1
@@ -0,0 +1,131 @@
+.\" opielogin.1: Manual page for the opielogin(1) program.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation.
+.\" Modified at NRL for OPIE 2.0.
+.\" Option descriptions added from BSD.
+.\" Written at Bellcore for the S/Key Version 1 software distribution
+.\" (keylogin.1).
+.\"
+.ll 6i
+.pl 10.5i
+.lt 6.0i
+.TH OPIELOGIN 1 "January 10, 1995"
+.AT 3
+
+.SH NAME
+opielogin \- Replacement for login(1) that issues OPIE challenges.
+
+.SH SYNOPSIS
+.B opielogin
+[ -p ] [ -r
+.I hostname
+| -h
+.I hostname
+| -f
+.I username
+.sp 0
+|
+.I username
+]
+
+.SH DESCRIPTION
+.I opielogin
+provides a replacement for the
+.IR login (1)
+program that provides OPIE challenges
+to users and accepts OPIE responses. It is downward compatible with the
+.IR keylogin(1)
+program from the Bellcore S/Key Version 1 distribution, which, in
+turn, is downward compatible with the
+.IR login(1)
+program from the 4.3BSD Net/2 distribution.
+
+.SH OPTIONS
+.TP
+.B \-p
+By default, login discards any previous environment. The \-p
+option disables this behavior.
+.TP
+.B \-r
+Process remote login from
+.I hostname.
+.TP
+.B \-h
+The -h option specifies the host from which the connection was
+received. It is used by various daemons such as telnetd(8).
+This option may only be used by the super\-user.
+.TP
+.B \-f
+The -f option is used when a user name is specified to indicate
+that proper authentication has already been done and that no
+password need be requested. This option may only be used by the
+super\-user or when an already logged in user is logging in as
+themselves.
+.TP
+.I username
+The user name to log in as.
+.SH EXAMPLE
+.sp 0
+wintermute$ opielogin
+.sp 0
+login: kebe
+.sp 0
+otp-md5 499 wi43143
+.sp 0
+Password: (echo on)
+.sp 0
+Password:SLY BLOB TOUR POP BRED EDDY
+.sp 0
+
+.sp 0
+ Welcome to wintermute.
+.sp 0
+
+.sp 0
+wintermute$
+.LP
+.SH FILES
+.TP
+/etc/opiekeys -- database of information for the OPIE system.
+.TP
+/etc/opieaccess -- list of safe and unsafe networks and masks to go with them.
+.TP
+$HOME/.opiealways -- presence makes OPIE for logins mandatory for the user.
+
+.SH SEE ALSO
+.BR login (1),
+.BR opie (4),
+.BR opiekey (1),
+.BR opiepasswd (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opieftpd (8),
+.BR opiekeys (5),
+.BR opieaccess (5)
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opielogin.c b/contrib/opie/opielogin.c
new file mode 100644
index 0000000..8189293
--- /dev/null
+++ b/contrib/opie/opielogin.c
@@ -0,0 +1,1428 @@
+/* opielogin.c: The infamous /bin/login
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Process login environment files.
+ Made logindevperm/fbtab handling more generic. Kluge around
+ Solaris drain bamage differently (maybe better?). Maybe
+ allow cleartext logins even when opiechallenge() fails.
+ Changed the conditions on when time.h and sys/time.h are
+ included. Send debug info to syslog. Use opielogin() instead
+ of dealing with utmp/setlogin() here.
+ Modified by cmetz for OPIE 2.22. Call setlogin(). Decreased default
+ timeout to two minutes. Use opiereadpass() flags to get
+ around Solaris drain bamage.
+ Modified by cmetz for OPIE 2.21. Took the sizeof() the wrong thing.
+ Modified by cmetz for OPIE 2.2. Changed prompts to ask for OTP
+ response where appropriate. Simple though small speed-up.
+ Don't allow cleartext if echo on. Don't try to clear
+ non-blocking I/O. Use opiereadpass(). Don't mess with
+ termios (as much, at least) -- that's opiereadpass()'s
+ job. Change opiereadpass() calls to add echo arg. Fixed
+ CONTROL macro. Don't modify argv (at least, unless
+ we have a reason to). Allow user in if ruserok() says
+ so. Removed useless strings (I don't think that
+ removing the ucb copyright one is a problem -- please
+ let me know if I'm wrong). Use FUNCTION declaration et
+ al. Moved definition of TRUE here. Ifdef around more
+ headers. Make everything static. Removed support for
+ omitting domain name if same domain -- it generally
+ didn't work and it would be a big portability problem.
+ Use opiereadpass() in getloginname() and then post-
+ process. Added code to grab hpux time zone from
+ /etc/src.sh. Renamed MAIL_DIR to PATH_MAIL. Removed
+ dupe catchexit and extraneous closelog. openlog() as
+ soon as possible because SunOS syslog is broken.
+ Don't print an extra blank line before a new Response
+ prompt.
+ Modified at NRL for OPIE 2.2. Changed strip_crlf to stripcrlf.
+ Do opiebackspace() on entries.
+ Modified at NRL for OPIE 2.1. Since we don't seem to use the
+ result of opiechallenge() anymore, discard it. Changed
+ BSD4_3 to HAVE_GETTTYNAM. Other symbol changes for
+ autoconf. Removed obselete usage comment. Removed
+ des_crypt.h. File renamed to opielogin.c. Added bletch
+ for setpriority. Added slash between MAIL_DIR and name.
+ Modified at NRL for OPIE 2.02. Flush stdio after printing login
+ prompt. Fixed Solaris shadow password problem introduced
+ in OPIE 2.01 (the shadow password structure is spwd, not
+ spasswd).
+ Modified at NRL for OPIE 2.01. Changed password lookup handling
+ to use a static structure to avoid problems with drain-
+ bamaged shadow password packages. Make sure to close
+ syslog by function to avoid problems with drain bamaged
+ syslog implementations. Log a few interesting errors.
+ Modified at NRL for OPIE 2.0.
+ Modified at Bellcore for the Bellcore S/Key Version 1 software
+ distribution.
+ Originally from BSD.
+*/
+/*
+ * Portions of this software are
+ * Copyright (c) 1980,1987 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#include "opie_cfg.h" /* OPIE: defines symbols for filenames & pathnames */
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else /* TIME_WITH_SYS_TIME */
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else /* HAVE_SYS_TIME_H */
+#include <time.h>
+#endif /* HAVE_SYS_TIME_H */
+#endif /* TIME_WITH_SYS_TIME */
+
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+#include <signal.h>
+#if HAVE_PWD_H
+#include <pwd.h> /* POSIX Password routines */
+#endif /* HAVE_PWD_H */
+#include <stdio.h>
+#include <errno.h>
+#if HAVE_UNISTD_H
+#include <unistd.h> /* Basic POSIX macros and functions */
+#endif /* HAVE_UNISTD_H */
+#include <termios.h> /* POSIX terminal I/O */
+#if HAVE_STRING_H
+#include <string.h> /* ANSI C string functions */
+#endif /* HAVE_STRING_H */
+#include <fcntl.h> /* File I/O functions */
+#include <syslog.h>
+#include <grp.h>
+#include <netdb.h>
+#include <netinet/in.h> /* contains types needed for next include file */
+#include <arpa/inet.h> /* Inet addr<-->ascii functions */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#ifdef QUOTA
+#include <sys/quota.h>
+#endif
+
+#if HAVE_GETTTYNAM
+#include <sys/ioctl.h> /* non-portable routines used only a few places */
+#include <ttyent.h>
+#endif /* HAVE_GETTTYNAM */
+
+#include "opie.h"
+
+#define TTYGID(gid) tty_gid(gid) /* gid that owns all ttys */
+
+#define NMAX 32
+#define HMAX 256
+
+#if HAVE_LASTLOG_H
+#include <lastlog.h>
+#endif /* HAVE_LASTLOG_H */
+
+static int rflag = 0;
+static int usererr = -1;
+static int stopmotd;
+static char rusername[NMAX + 1];
+static char name[NMAX + 1] = "";
+static char minusnam[16] = "-";
+static char *envinit[1]; /* now set by setenv calls */
+static char term[64] = "\0"; /* important to initialise to a NULL string */
+static char host[HMAX + 1] = "\0";
+static struct passwd nouser;
+static struct passwd thisuser;
+
+#if HAVE_SHADOW_H
+#include <shadow.h>
+#endif /* HAVE_SHADOW_H */
+
+static char *ttyprompt;
+
+#ifdef PERMSFILE
+extern char *home;
+#endif /* PERMSFILE */
+
+static struct termios attr;
+
+extern int errno;
+
+static int ouroptind;
+static char *ouroptarg;
+
+#if HAVE_LASTLOG_H
+#ifndef _PATH_LASTLOG
+#define _PATH_LASTLOG "/var/adm/lastlog"
+#endif /* _PATH_LASTLOG */
+
+static char lastlog[] = _PATH_LASTLOG;
+#endif /* HAVE_LASTLOG_H */
+
+/*
+ * The "timeout" variable bounds the time given to login.
+ * We initialize it here for safety and so that it can be
+ * patched on machines where the default value is not appropriate.
+ */
+static int timeout = 120;
+
+static void getstr __P((char *, int, char *));
+
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif /* HAVE_CRYPT_H */
+
+#undef TRUE
+#define TRUE -1
+
+#ifdef TIOCSWINSZ
+/* Windowing variable relating to JWINSIZE/TIOCSWINSZ/TIOCGWINSZ. This is
+available on BSDish systems and at least Solaris 2.x, but portability to
+other systems is questionable. Use within this source code module is
+protected by suitable defines.
+
+I'd be interested in hearing about a more portable approach. rja */
+
+static struct winsize win = {0, 0, 0, 0};
+#endif
+
+
+/*------------------ BEGIN REAL CODE --------------------------------*/
+
+/* We allow the malloc()s to potentially leak data out because we can
+only call this routine about four times in the lifetime of this process
+and the kernel will free all heap memory when we exit or exec. */
+static int lookupuser FUNCTION_NOARGS
+{
+ struct passwd *pwd;
+#if HAVE_SHADOW
+ struct spwd *spwd;
+#endif /* HAVE_SHADOW */
+
+ memcpy(&thisuser, &nouser, sizeof(thisuser));
+
+ if (!(pwd = getpwnam(name)))
+ return -1;
+
+ thisuser.pw_uid = pwd->pw_uid;
+ thisuser.pw_gid = pwd->pw_gid;
+
+ if (!(thisuser.pw_name = malloc(strlen(pwd->pw_name) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_name, pwd->pw_name);
+
+ if (!(thisuser.pw_dir = malloc(strlen(pwd->pw_dir) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_dir, pwd->pw_dir);
+
+ if (!(thisuser.pw_shell = malloc(strlen(pwd->pw_shell) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_shell, pwd->pw_shell);
+
+#if HAVE_SHADOW
+ if (!(spwd = getspnam(name)))
+ goto lookupuserbad;
+
+ pwd->pw_passwd = spwd->sp_pwdp;
+
+ endspent();
+#endif /* HAVE_SHADOW */
+
+ if (!(thisuser.pw_passwd = malloc(strlen(pwd->pw_passwd) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_passwd, pwd->pw_passwd);
+
+ endpwent();
+
+ return ((thisuser.pw_passwd[0] == '*') || (thisuser.pw_passwd[0] == '#'));
+
+lookupuserbad:
+ memcpy(&thisuser, &nouser, sizeof(thisuser));
+ return -1;
+}
+
+static VOIDRET getloginname FUNCTION_NOARGS
+{
+ register char *namep;
+ char c, d;
+ int flags;
+ static int first = 1;
+
+ memset(name, 0, sizeof(name));
+
+ d = 0;
+ while (name[0] == '\0') {
+ flags = 1;
+ if (ttyprompt) {
+ if (first) {
+ flags = 4;
+ first--;
+ } else
+ printf(ttyprompt);
+ } else
+ printf("login: ");
+ fflush(stdout);
+ if (++d == 3)
+ exit(0);
+ if (!opiereadpass(name, sizeof(name)-1, flags)) {
+ syslog(LOG_CRIT, "End-of-file (or other error?) on stdin!");
+ exit(0);
+ }
+ for (namep = name; *namep; namep++) {
+ if (c == ' ')
+ c = '_';
+ }
+ }
+}
+
+static VOIDRET timedout FUNCTION((i), int i)
+{
+ /* input variable declared just to keep the compiler quiet */
+ printf("Login timed out after %d seconds\n", timeout);
+ syslog(LOG_CRIT, "Login timed out after %d seconds!", timeout);
+ exit(0);
+}
+
+#if !HAVE_MOTD_IN_PROFILE
+static VOIDRET catch FUNCTION((i), int i)
+{
+ /* the input variable is declared to keep the compiler quiet */
+ signal(SIGINT, SIG_IGN);
+ stopmotd++;
+}
+#endif /* !HAVE_MOTD_IN_PROFILE */
+
+static VOIDRET catchexit FUNCTION_NOARGS
+{
+ int i;
+ tcsetattr(STDIN_FILENO, TCSANOW, &attr);
+ putchar('\n');
+ closelog();
+ for (i = sysconf(_SC_OPEN_MAX); i > 2; i--)
+ close(i);
+}
+
+static int rootterm FUNCTION((ttyn), char *ttyn)
+{
+#if HAVE_GETTTYNAM
+/* The getttynam() call and the ttyent structure first appeared in 4.3 BSD and
+are not portable to System V systems such as Solaris 2.x. or modern versions
+of IRIX rja */
+ register struct ttyent *t;
+ char *tty;
+
+ tty = strrchr(ttyn, '/');
+
+ if (tty == NULL)
+ tty = ttyn;
+ else
+ tty++;
+
+ if ((t = getttynam(tty)) != NULL)
+ return (t->ty_status & TTY_SECURE);
+
+ return (1); /* when in doubt, allow root logins */
+
+#elif HAVE_ETC_DEFAULT_LOGIN
+
+ FILE *filno;
+ char line[128];
+ char *next, *next2;
+
+/* SVR4 only permits two security modes for root logins: 1) only from CONSOLE,
+if the string "CONSOLE=/dev/console" exists and is not commented out with "#"
+characters, or 2) from anywhere.
+
+So we open /etc/default/login file grab the file contents one line at a time
+verify that the line being tested isn't commented out check for the substring
+"CONSOLE" and decide whether to permit this attempted root login/su. */
+
+ if ((filno = fopen("/etc/default/login", "r")) != NULL) {
+ while (fgets(line, 128, filno) != NULL) {
+ next = line;
+
+ if ((line[0] != '#') && (next = strstr(line, "CONSOLE"))) {
+ next += 7; /* get past the string "CONSOLE" */
+
+ while (*next && (*next == ' ') || (*next == '\t'))
+ next++;
+
+ if (*(next++) != '=')
+ break; /* some weird character, get next line */
+
+ next2 = next;
+ while (*next2 && (*next2 != '\t') && (*next2 != ' ') &&
+ (*next2 != '\n'))
+ next2++;
+ *next2 = 0;
+
+ return !strcmp(ttyn, next); /* Allow the login if and only if the
+ user's terminal line matches the
+ setting for CONSOLE */
+ }
+ } /* end while another line could be obtained */
+ } /* end if could open file */
+ return (1); /* when no CONSOLE line exists, root can login from anywhere */
+#elif HAVE_SECURETTY
+ {
+ FILE *f;
+ char buffer[1024], *c;
+ int rc = 0;
+
+ if (!(f = fopen("/etc/securetty", "r")))
+ return 1;
+
+ if (c = strstr(ttyn, "/dev/"))
+ ttyn += 5;
+
+ if (c = strrchr(ttyn, '/'))
+ ttyn = ++c;
+
+ while (fgets(buffer, sizeof(buffer), f)) {
+ if (c = strrchr(buffer, '\n'))
+ *c = 0;
+
+ if (!(c = strrchr(buffer, '/')))
+ c = buffer;
+ else
+ c++;
+
+ if (!strcmp(c, ttyn))
+ rc = 1;
+ };
+
+ fclose(f);
+ return rc;
+ }
+#else
+ return (1); /* when in doubt, allow root logins */
+#endif
+}
+
+static int doremotelogin FUNCTION((host), char *host)
+{
+ int rc;
+
+ getstr(rusername, sizeof(rusername), "remuser");
+ getstr(name, sizeof(name), "locuser");
+ getstr(term, sizeof(term), "Terminal type");
+ if (getuid()) {
+ memcpy(&thisuser, &nouser, sizeof(thisuser));
+ syslog(LOG_ERR, "getuid() failed");
+ return (-1);
+ }
+ if (lookupuser()) {
+ syslog(LOG_ERR, "lookup failed for user %s", name);
+ return (-1);
+ }
+ rc = ruserok(host, !thisuser.pw_uid, rusername, name);
+ if (rc == -1) {
+ syslog(LOG_ERR,
+ "ruserok failed, host=%s, uid=%d, remote username=%s, local username=%s",
+ host, thisuser.pw_uid, rusername, name);
+ }
+ return rc;
+}
+
+
+static VOIDRET getstr FUNCTION((buf, cnt, err), char *buf AND int cnt AND char *err)
+{
+ char c;
+
+ do {
+ if (read(0, &c, 1) != 1)
+ exit(1);
+ if (--cnt < 0) {
+ printf("%s too long\r\n", err);
+ syslog(LOG_CRIT, "%s too long", err);
+ exit(1);
+ }
+ *buf++ = c;
+ }
+ while ((c != 0) && (c != '~'));
+}
+
+struct speed_xlat {
+ char *c;
+ int i;
+} speeds[] = {
+
+#ifdef B0
+ {
+ "0", B0
+ },
+#endif /* B0 */
+#ifdef B50
+ {
+ "50", B50
+ },
+#endif /* B50 */
+#ifdef B75
+ {
+ "75", B75
+ },
+#endif /* B75 */
+#ifdef B110
+ {
+ "110", B110
+ },
+#endif /* B110 */
+#ifdef B134
+ {
+ "134", B134
+ },
+#endif /* B134 */
+#ifdef B150
+ {
+ "150", B150
+ },
+#endif /* B150 */
+#ifdef B200
+ {
+ "200", B200
+ },
+#endif /* B200 */
+#ifdef B300
+ {
+ "300", B300
+ },
+#endif /* B300 */
+#ifdef B600
+ {
+ "600", B600
+ },
+#endif /* B600 */
+#ifdef B1200
+ {
+ "1200", B1200
+ },
+#endif /* B1200 */
+#ifdef B1800
+ {
+ "1800", B1800
+ },
+#endif /* B1800 */
+#ifdef B2400
+ {
+ "2400", B2400
+ },
+#endif /* B2400 */
+#ifdef B4800
+ {
+ "4800", B4800
+ },
+#endif /* B4800 */
+#ifdef B7200
+ {
+ "7200", B7200
+ },
+#endif /* B7200 */
+#ifdef B9600
+ {
+ "9600", B9600
+ },
+#endif /* B9600 */
+#ifdef B14400
+ {
+ "14400", B14400
+ },
+#endif /* B14400 */
+#ifdef B19200
+ {
+ "19200", B19200
+ },
+#endif /* B19200 */
+#ifdef B28800
+ {
+ "28800", B28800
+ },
+#endif /* B28800 */
+#ifdef B38400
+ {
+ "38400", B38400
+ },
+#endif /* B38400 */
+#ifdef B57600
+ {
+ "57600", B57600
+ },
+#endif /* B57600 */
+#ifdef B115200
+ {
+ "115200", B115200
+ },
+#endif /* B115200 */
+#ifdef B230400
+ {
+ "230400", B230400
+ },
+#endif /* 230400 */
+ {
+ NULL, 0
+ }
+};
+
+static VOIDRET doremoteterm FUNCTION((term), char *term)
+{
+ register char *cp = strchr(term, '/');
+ char *speed;
+ struct speed_xlat *x;
+
+ if (cp) {
+ *cp++ = '\0';
+ speed = cp;
+ cp = strchr(speed, '/');
+ if (cp)
+ *cp++ = '\0';
+ for (x = speeds; x->c != NULL; x++)
+ if (strcmp(x->c, speed) == 0) {
+ cfsetispeed(&attr, x->i);
+ cfsetospeed(&attr, x->i);
+ break;
+ }
+ }
+}
+
+static int tty_gid FUNCTION((default_gid), int default_gid)
+{
+ struct group *gr;
+ int gid = default_gid;
+
+ gr = getgrnam(TTYGRPNAME);
+ if (gr != (struct group *) 0)
+ gid = gr->gr_gid;
+ endgrent();
+ return (gid);
+}
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ extern char **environ;
+ register char *namep;
+ struct opie opie;
+
+ int invalid, quietlog;
+ FILE *nlfd;
+ char *tty, host[256];
+ int pflag = 0, hflag = 0, fflag = 0;
+ int t, c;
+ int i;
+ char *p;
+ char opieprompt[OPIE_CHALLENGE_MAX + 1];
+ int pwok, otpok, af_pwok;
+ char *pp;
+ char buf[256];
+ int uid;
+ int opiepassed;
+
+#ifndef DEBUG
+ if (geteuid()) {
+ fprintf(stderr, "This program requires super-user priveleges.\n");
+ exit(1);
+ }
+#endif /* DEBUG */
+
+ openlog("login", LOG_ODELAY, LOG_AUTH);
+
+ {
+ struct termios termios;
+ fd_set fds;
+ struct timeval timeval;
+
+ memset(&timeval, 0, sizeof(struct timeval));
+
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+
+ if (select(1, &fds, NULL, NULL, &timeval)) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "reading user name from tty buffer");
+#endif /* DEBUG */
+
+ if (tcgetattr(0, &termios)) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "tcgetattr(0, &termios) failed");
+#endif /* DEBUG */
+ exit(1);
+ }
+
+ termios.c_lflag &= ~ECHO;
+
+ if (tcsetattr(0, TCSANOW, &termios)) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "tcsetattr(0, &termios) failed");
+#endif /* DEBUG */
+ exit(1);
+ }
+
+ if ((i = read(0, name, sizeof(name)-1)) > 0)
+ name[i] = 0;
+ }
+ }
+
+ /* initialisation */
+ host[0] = '\0';
+ opieprompt[0] = '\0';
+
+ if (p = getenv("TERM")) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "environment TERM=%s", p);
+#endif /* DEBUG */
+ strncpy(term, p, sizeof(term));
+ };
+
+ memset(&nouser, 0, sizeof(nouser));
+ nouser.pw_uid = -1;
+ nouser.pw_gid = -1;
+ nouser.pw_passwd = "#nope";
+ nouser.pw_name = nouser.pw_gecos = nouser.pw_dir = nouser.pw_shell = "";
+
+#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H
+ setpriority(PRIO_PROCESS, 0, 0);
+#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
+
+ signal(SIGALRM, timedout);
+ alarm(timeout);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+
+#if DOTTYPROMPT
+ ttyprompt = (char *) getenv("TTYPROMPT");
+#endif /* TTYPROMPT */
+
+#ifdef QUOTA
+ quota(Q_SETUID, 0, 0, 0);
+#endif
+
+#ifdef DEBUG
+ {
+ int foo;
+
+ syslog(LOG_DEBUG, "my args are: (argc=%d)", foo = argc);
+ while (--foo)
+ syslog(LOG_DEBUG, "%d: %s", foo, argv[foo]);
+ }
+#endif /* DEBUG */
+
+/* Some OSs pass environment variables on the command line. All of them except
+ for TERM get eaten. */
+
+ i = argc;
+ while (--i)
+ if (strchr(argv[i], '=')) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "eating %s", argv[i]);
+#endif /* DEBUG */
+ argc--;
+ if (!strncmp(argv[i], "TERM=", 5)) {
+ strncpy(term, &(argv[i][5]), sizeof(term));
+ term[sizeof(term) - 1] = 0;
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "passed TERM=%s, ouroptind = %d", term, i);
+#endif /* DEBUG */
+ }
+ }
+/* Implement our own getopt()-like functionality, but do so in a much more
+ strict manner to prevent security problems. */
+ for (ouroptind = 1; ouroptind < argc; ouroptind++) {
+ i = 0;
+ if (argv[ouroptind])
+ if (argv[ouroptind][0] == '-')
+ if (i = argv[ouroptind][1])
+ if (!argv[ouroptind][2])
+ switch (i) {
+ case 'd':
+ if (++ouroptind == argc)
+ exit(1);
+/* The '-d' option is apparently a performance hack to get around
+ ttyname() being slow. The potential does exist for it to be used
+ for malice, and it does not seem to be strictly necessary, so we
+ will just eat it. */
+ break;
+
+ case 'r':
+ if (rflag || hflag || fflag) {
+ printf("Other options not allowed with -r\n");
+ exit(1);
+ }
+ if (++ouroptind == argc)
+ exit(1);
+
+ ouroptarg = argv[ouroptind];
+
+ if (!ouroptarg)
+ exit(1);
+
+ rflag = -1;
+ if (!doremotelogin(ouroptarg))
+ rflag = 1;
+
+ strncpy(host, ouroptarg, sizeof(host));
+ break;
+
+ case 'h':
+ if (!getuid()) {
+ if (rflag || hflag || fflag) {
+ printf("Other options not allowed with -h\n");
+ exit(1);
+ }
+ hflag = 1;
+
+ if (++ouroptind == argc)
+ exit(1);
+
+ ouroptarg = argv[ouroptind];
+
+ if (!ouroptarg)
+ exit(1);
+
+ strncpy(host, ouroptarg, sizeof(host));
+ }
+ break;
+
+ case 'f':
+ if (rflag) {
+ printf("Only one of -r and -f allowed\n");
+ exit(1);
+ }
+ fflag = 1;
+
+ if (++ouroptind == argc)
+ exit(1);
+
+ ouroptarg = argv[ouroptind];
+
+ if (!ouroptarg)
+ exit(1);
+
+ strncpy(name, ouroptarg, sizeof(name));
+ break;
+
+ case 'p':
+ pflag = 1;
+ break;
+ } else
+ i = 0;
+ if (!i) {
+ ouroptarg = argv[ouroptind++];
+ strncpy(name, ouroptarg, sizeof(name));
+ break;
+ }
+ }
+
+ for (t = sysconf(_SC_OPEN_MAX); t > 2; t--)
+ close(t);
+
+#ifdef TIOCNXCL
+ /* BSDism: not sure how to rewrite for POSIX. rja */
+ ioctl(0, TIOCNXCL, 0); /* set non-exclusive use of tty */
+#endif
+
+ /* get original termio attributes */
+ if (tcgetattr(STDIN_FILENO, &attr) != 0)
+ return (-1);
+
+/* If talking to an rlogin process, propagate the terminal type and baud rate
+ across the network. */
+ if (rflag)
+ doremoteterm(term);
+
+/* Force termios portable control characters to the system default values as
+specified in termios.h. This should help the one-time password login feel the
+same as the vendor-supplied login. Common extensions are also set for
+completeness, but these are set within appropriate defines for portability. */
+
+#define CONTROL(x) (x - 64)
+
+#ifdef VEOF
+#ifdef CEOF
+ attr.c_cc[VEOF] = CEOF;
+#else /* CEOF */
+ attr.c_cc[VEOF] = CONTROL('D');
+#endif /* CEOF */
+#endif /* VEOF */
+#ifdef VEOL
+#ifdef CEOL
+ attr.c_cc[VEOL] = CEOL;
+#else /* CEOL */
+ attr.c_cc[VEOL] = CONTROL('J');
+#endif /* CEOL */
+#endif /* VEOL */
+#ifdef VERASE
+#ifdef CERASE
+ attr.c_cc[VERASE] = CERASE;
+#else /* CERASE */
+ attr.c_cc[VERASE] = CONTROL('H');
+#endif /* CERASE */
+#endif /* VERASE */
+#ifdef VINTR
+#ifdef CINTR
+ attr.c_cc[VINTR] = CINTR;
+#else /* CINTR */
+ attr.c_cc[VINTR] = CONTROL('C');
+#endif /* CINTR */
+#endif /* VINTR */
+#ifdef VKILL
+#ifdef CKILL
+ attr.c_cc[VKILL] = CKILL;
+#else /* CKILL */
+ attr.c_cc[VKILL] = CONTROL('U');
+#endif /* CKILL */
+#endif /* VKILL */
+#ifdef VQUIT
+#ifdef CQUIT
+ attr.c_cc[VQUIT] = CQUIT;
+#else /* CQUIT */
+ attr.c_cc[VQUIT] = CONTROL('\\');
+#endif /* CQUIT */
+#endif /* VQUIT */
+#ifdef VSUSP
+#ifdef CSUSP
+ attr.c_cc[VSUSP] = CSUSP;
+#else /* CSUSP */
+ attr.c_cc[VSUSP] = CONTROL('Z');
+#endif /* CSUSP */
+#endif /* VSUSP */
+#ifdef VSTOP
+#ifdef CSTOP
+ attr.c_cc[VSTOP] = CSTOP;
+#else /* CSTOP */
+ attr.c_cc[VSTOP] = CONTROL('S');
+#endif /* CSTOP */
+#endif /* VSTOP */
+#ifdef VSTART
+#ifdef CSTART
+ attr.c_cc[VSTART] = CSTART;
+#else /* CSTART */
+ attr.c_cc[VSTART] = CONTROL('Q');
+#endif /* CSTART */
+#endif /* VSTART */
+#ifdef VDSUSP
+#ifdef CDSUSP
+ attr.c_cc[VDSUSP] = CDSUSP;
+#else /* CDSUSP */
+ attr.c_cc[VDSUSP] = 0;
+#endif /* CDSUSP */
+#endif /* VDSUSP */
+#ifdef VEOL2
+#ifdef CEOL2
+ attr.c_cc[VEOL2] = CEOL2;
+#else /* CEOL2 */
+ attr.c_cc[VEOL2] = 0;
+#endif /* CEOL2 */
+#endif /* VEOL2 */
+#ifdef VREPRINT
+#ifdef CRPRNT
+ attr.c_cc[VREPRINT] = CRPRNT;
+#else /* CRPRNT */
+ attr.c_cc[VREPRINT] = 0;
+#endif /* CRPRNT */
+#endif /* VREPRINT */
+#ifdef VWERASE
+#ifdef CWERASE
+ attr.c_cc[VWERASE] = CWERASE;
+#else /* CWERASE */
+ attr.c_cc[VWERASE] = 0;
+#endif /* CWERASE */
+#endif /* VWERASE */
+#ifdef VLNEXT
+#ifdef CLNEXT
+ attr.c_cc[VLNEXT] = CLNEXT;
+#else /* CLNEXT */
+ attr.c_cc[VLNEXT] = 0;
+#endif /* CLNEXT */
+#endif /* VLNEXT */
+
+ attr.c_lflag |= ICANON; /* enable canonical input processing */
+ attr.c_lflag &= ~ISIG; /* disable INTR, QUIT,& SUSP signals */
+ attr.c_lflag |= (ECHO | ECHOE); /* enable echo and erase */
+#ifdef ONLCR
+ /* POSIX does not specify any output processing flags, but the usage below
+ is SVID compliant and is generally portable to modern versions of UNIX. */
+ attr.c_oflag |= ONLCR; /* map CR to CRNL on output */
+#endif
+#ifdef ICRNL
+ attr.c_iflag |= ICRNL;
+#endif /* ICRNL */
+
+ attr.c_oflag |= OPOST;
+ attr.c_lflag |= ICANON; /* enable canonical input */
+ attr.c_lflag |= ECHO;
+ attr.c_lflag |= ECHOE; /* enable ERASE character */
+ attr.c_lflag |= ECHOK; /* enable KILL to delete line */
+ attr.c_cflag |= HUPCL; /* hangup on close */
+
+ /* Set revised termio attributes */
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &attr))
+ return (-1);
+
+ atexit(catchexit);
+
+ tty = ttyname(0);
+
+ if (tty == (char *) 0 || *tty == '\0')
+ tty = "UNKNOWN"; /* was: "/dev/tty??" */
+
+#if HAVE_SETVBUF && defined(_IONBF)
+#if SETVBUF_REVERSED
+ setvbuf(stdout, _IONBF, NULL, 0);
+ setvbuf(stderr, _IONBF, NULL, 0);
+#else /* SETVBUF_REVERSED */
+ setvbuf(stdout, NULL, _IONBF, 0);
+ setvbuf(stderr, NULL, _IONBF, 0);
+#endif /* SETVBUF_REVERSED */
+#endif /* HAVE_SETVBUF && defined(_IONBF) */
+
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "tty = %s", tty);
+#endif /* DEBUG */
+
+#ifdef HAVE_LOGIN_ENVFILE
+ {
+ FILE *f;
+
+ if (f = fopen(HAVE_LOGIN_ENVFILE, "r")) {
+ char line[128], *c, *c2;
+
+ while(fgets(line, sizeof(line)-1, f)) {
+ c = line;
+ while(*c && (isalnum(*c) || (*c == '_'))) c++;
+ if (*c == '=') {
+ *(c++) = 0;
+ if (c2 = strchr(c, ';'))
+ *c2 = 0;
+ if (c2 = strchr(c, '\n'))
+ *c2 = 0;
+ if (c2 = strchr(c, ' '))
+ continue;
+ if (c2 = strchr(c, '\t'))
+ continue;
+ if (!strcmp(line, "TZ"))
+ continue;
+ if (setenv(line, c, 1) < 0) {
+ fprintf(stderr, "setenv() failed -- environment full?\n");
+ break;
+ }
+ }
+ }
+ fclose(f);
+ }
+ }
+#endif /* HAVE_LOGIN_ENVFILE */
+
+ t = 0;
+ invalid = TRUE;
+ af_pwok = opieaccessfile(host);
+
+ if (name[0])
+ if (name[0] == '-') {
+ fprintf(stderr, "User names can't start with '-'.\n");
+ syslog(LOG_AUTH, "Attempt to use invalid username: %s.", name);
+ exit(1);
+ } else
+ invalid = lookupuser();
+
+ do {
+ /* If remote login take given name, otherwise prompt user for something. */
+ if (invalid && !name[0]) {
+ getloginname();
+ invalid = lookupuser();
+ }
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "login name is +%s+, of length %d, [0] = %d", name, strlen(name), name[0]);
+#endif /* DEBUG */
+
+ if (fflag) {
+ uid = getuid();
+
+ if (uid != 0 && uid != thisuser.pw_uid)
+ fflag = 0;
+ /* Disallow automatic login for root. */
+ if (thisuser.pw_uid == 0)
+ fflag = 0;
+ }
+ if (feof(stdin))
+ exit(0);
+
+ /* If no remote login authentication and a password exists for this user,
+ prompt for and verify a password. */
+ if (!fflag && (rflag < 1) && *thisuser.pw_passwd) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "login name is +%s+, of length %d, [0] = %d\n", name, strlen(name), name[0]);
+#endif /* DEBUG */
+
+ /* Attempt a one-time password challenge */
+ i = opiechallenge(&opie, name, opieprompt);
+
+ if ((i < 0) || (i > 1)) {
+ syslog(LOG_ERR, "error: opiechallenge() returned %d, errno=%d!\n", i, errno);
+ fprintf(stderr, "System error; can't issue challenge!\n");
+ otpok = 0;
+ } else {
+ printf("%s\n", opieprompt);
+ otpok = 1;
+ }
+
+ if (!memcmp(&thisuser, &nouser, sizeof(thisuser)))
+ if (host[0])
+ syslog(LOG_WARNING, "Invalid login attempt for %s on %s from %s.",
+ name, tty, host);
+ else
+ syslog(LOG_WARNING, "Invalid login attempt for %s on %s.",
+ name, tty);
+
+ pwok = af_pwok && opiealways(thisuser.pw_dir);
+#if DEBUG
+ syslog(LOG_DEBUG, "af_pwok = %d, pwok = %d", af_pwok, pwok);
+#endif /* DEBUG */
+
+ if (!pwok && !otpok) {
+ fprintf(stderr, "Can't authenticate %s!\n");
+ continue;
+ }
+
+#if NEW_PROMPTS
+ if (otpok)
+ printf("Response");
+ if (otpok && pwok)
+ printf(" or ");
+ if (pwok)
+ printf("Password");
+ printf(": ");
+ if (!opiereadpass(buf, sizeof(buf), !pwok))
+ invalid = TRUE;
+#else /* NEW_PROMPTS */
+ if (!pwok)
+ printf("(OTP response required)\n");
+ printf("Password:");
+ fflush(stdout);
+ if (!opiereadpass(buf, sizeof(buf), 0))
+ invalid = TRUE;
+#endif /* NEW_PROMPTS */
+
+ if (!buf[0] && otpok) {
+ pwok = 0;
+ /* Null line entered, so display appropriate prompt & flush current
+ data. */
+#if NEW_PROMPTS
+ printf("Response: ");
+#else /* NEW_PROMPTS */
+ printf(" (echo on)\nPassword:");
+#endif /* NEW_PROMPTS */
+ if (!opiereadpass(buf, sizeof(buf), 1))
+ invalid = TRUE;
+ }
+
+ if (otpok) {
+ i = opiegetsequence(&opie);
+ opiepassed = !opieverify(&opie, buf);
+
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "opiepassed = %d", opiepassed);
+#endif /* DEBUG */
+ }
+
+ if (!invalid) {
+ if (otpok && opiepassed) {
+ if (i < 10) {
+ printf("Warning: Re-initialize your OTP information");
+ if (i < 5)
+ printf(" NOW!");
+ printf("\n");
+ }
+ } else {
+ if (pwok) {
+ pp = crypt(buf, thisuser.pw_passwd);
+ invalid = strcmp(pp, thisuser.pw_passwd);
+ } else
+ invalid = TRUE;
+ }
+ }
+ }
+
+ /* If user not super-user, check for logins disabled. */
+ if (thisuser.pw_uid) {
+ if (nlfd = fopen(NO_LOGINS_FILE, "r")) {
+ while ((c = getc(nlfd)) != EOF)
+ putchar(c);
+ fflush(stdout);
+ sleep(5);
+ exit(0);
+ }
+ }
+ /* If valid so far and root is logging in, see if root logins on this
+ terminal are permitted. */
+ if (!invalid && !thisuser.pw_uid && !rootterm(tty)) {
+ if (host[0])
+ syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s FROM %.*s",
+ tty, HMAX, host);
+ else
+ syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s", tty);
+ invalid = TRUE;
+ }
+ /* If invalid, then log failure attempt data to appropriate system
+ logfiles and close the connection. */
+ if (invalid) {
+ printf("Login incorrect\n");
+ if (host[0])
+ syslog(LOG_ERR, "LOGIN FAILURE ON %s FROM %.*s, %.*s",
+ tty, HMAX, host, sizeof(name), name);
+ else
+ syslog(LOG_ERR, "LOGIN FAILURE ON %s, %.*s",
+ tty, sizeof(name), name);
+ if (++t >= 5)
+ exit(1);
+ }
+ if (*thisuser.pw_shell == '\0')
+ thisuser.pw_shell = "/bin/sh";
+ if ((chdir(thisuser.pw_dir) < 0) && !invalid) {
+ if (chdir("/") < 0) {
+ printf("No directory!\n");
+ invalid = TRUE;
+ } else {
+ printf("No directory! %s\n", "Logging in with HOME=/");
+ strcpy(thisuser.pw_dir, "/");
+ }
+ }
+ /* Remote login invalid must have been because of a restriction of some
+ sort, no extra chances. */
+ if (invalid) {
+ if (!usererr)
+ exit(1);
+ name[0] = 0;
+ }
+ }
+ while (invalid);
+ /* Committed to login -- turn off timeout */
+ alarm(0);
+
+#ifdef QUOTA
+ if (quota(Q_SETUID, thisuser.pw_uid, 0, 0) < 0 && errno != EINVAL) {
+ if (errno == EUSERS)
+ printf("%s.\n%s.\n", "Too many users logged on already",
+ "Try again later");
+ else
+ if (errno == EPROCLIM)
+ printf("You have too many processes running.\n");
+ else
+ perror("quota (Q_SETUID)");
+ sleep(5);
+ exit(0);
+ }
+#endif
+
+ if (opielogin(tty, name, host))
+ syslog(LOG_ERR, "can't record login: tty %s, name %s, host %s", tty, name, host);
+
+ quietlog = !access(QUIET_LOGIN_FILE, F_OK);
+
+#if HAVE_LASTLOG_H
+ {
+ int f;
+
+ if ((f = open(lastlog, O_RDWR)) >= 0) {
+ struct lastlog ll;
+
+ lseek(f, (long)thisuser.pw_uid * sizeof(struct lastlog), 0);
+
+ if ((sizeof(ll) == read(f, (char *) &ll, sizeof(ll))) &&
+ (ll.ll_time != 0) && (!quietlog)) {
+ printf("Last login: %.*s ",
+ 24 - 5, (char *) ctime(&ll.ll_time));
+ if (*ll.ll_host != '\0')
+ printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host);
+ else
+ printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line);
+ }
+ lseek(f, (long)thisuser.pw_uid * sizeof(struct lastlog), 0);
+
+ time(&ll.ll_time);
+ strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+ strncpy(ll.ll_host, host, sizeof(ll.ll_host));
+ write(f, (char *) &ll, sizeof ll);
+ close(f);
+ }
+ }
+#endif /* HAVE_LASTLOG_H */
+
+ chown(tty, thisuser.pw_uid, TTYGID(thisuser.pw_gid));
+
+#ifdef TIOCSWINSZ
+/* POSIX does not specify any interface to set/get window sizes, so this is
+not portable. It should work on most recent BSDish systems and the defines
+should protect it on older System Vish systems. It does work under Solaris
+2.4, though it isn't clear how many other SVR4 systems support it. I'd be
+interested in hearing of a more portable approach. rja */
+ if (!hflag && !rflag)
+ ioctl(0, TIOCSWINSZ, &win); /* set window size to 0,0,0,0 */
+#endif
+
+ chmod(tty, 0622);
+ setgid(thisuser.pw_gid);
+ initgroups(name, thisuser.pw_gid);
+
+#ifdef QUOTA
+ quota(Q_DOWARN, thisuser.pw_uid, (dev_t) - 1, 0);
+#endif
+
+#ifdef PERMSFILE
+ home = thisuser.pw_dir;
+ permsfile(name, tty, thisuser.pw_uid, thisuser.pw_gid);
+ fflush(stderr);
+#endif /* PERMSFILE */
+
+ setuid(thisuser.pw_uid);
+
+ /* destroy environment unless user has asked to preserve it */
+ if (!pflag)
+ environ = envinit;
+ setenv("HOME", thisuser.pw_dir, 1);
+ setenv("SHELL", thisuser.pw_shell, 1);
+ if (!term[0]) {
+#if HAVE_GETTTYNAM
+/*
+ * The getttynam() call and the ttyent structure first appeared in 4.3 BSD.
+ * They are not portable to System V systems such as Solaris 2.x.
+ * rja
+ */
+ register struct ttyent *t;
+ register char *c;
+
+ if (c = strrchr(tty, '/'))
+ c++;
+ else
+ c = tty;
+
+ if (t = getttynam(c))
+ strncpy(term, t->ty_type, sizeof(term));
+ else
+#endif /* HAVE_GETTTYNAM */
+ strcpy(term, "unknown");
+ }
+
+ setenv("USER", name, 1);
+ setenv("LOGNAME", name, 1);
+ setenv("PATH", DEFAULT_PATH, 0);
+ if (term[0]) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "setting TERM=%s", term);
+#endif /* DEBUG */
+ setenv("TERM", term, 1);
+ }
+
+#ifdef HAVE_LOGIN_ENVFILE
+ {
+ FILE *f;
+
+ if (f = fopen(HAVE_LOGIN_ENVFILE, "r")) {
+ char line[128], *c, *c2;
+
+ while(fgets(line, sizeof(line)-1, f)) {
+ c = line;
+ while(*c && (isalnum(*c) || (*c == '_'))) c++;
+ if (*c == '=') {
+ *(c++) = 0;
+ if (c2 = strchr(c, ';'))
+ *c2 = 0;
+ if (c2 = strchr(c, '\n'))
+ *c2 = 0;
+ if (c2 = strchr(c, ' '))
+ continue;
+ if (c2 = strchr(c, '\t'))
+ continue;
+ if (setenv(line, c, 0) < 0) {
+ fprintf(stderr, "setenv() failed -- environment full?\n");
+ break;
+ }
+ }
+ }
+ fclose(f);
+ }
+ }
+#endif /* HAVE_LOGIN_ENVFILE */
+
+ if ((namep = strrchr(thisuser.pw_shell, '/')) == NULL)
+ namep = thisuser.pw_shell;
+ else
+ namep++;
+ strcat(minusnam, namep);
+ if (tty[sizeof("tty") - 1] == 'd')
+ syslog(LOG_INFO, "DIALUP %s, %s", tty, name);
+ if (!thisuser.pw_uid)
+ if (host[0])
+ syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", tty, HMAX, host);
+ else
+ syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
+#if !HAVE_MOTD_IN_PROFILE
+ if (!quietlog) {
+ FILE *mf;
+ register c;
+
+ signal(SIGINT, catch);
+ if ((mf = fopen(MOTD_FILE, "r")) != NULL) {
+ while ((c = getc(mf)) != EOF && !stopmotd)
+ putchar(c);
+ fclose(mf);
+ }
+ signal(SIGINT, SIG_IGN);
+ }
+#endif /* !HAVE_MOTD_IN_PROFILE */
+#if !HAVE_MAILCHECK_IN_PROFILE
+ if (!quietlog) {
+ struct stat st;
+ char buf[128];
+ int len;
+
+ strncpy(buf, PATH_MAIL, sizeof(buf) - 2);
+ buf[sizeof(buf) - 2] = 0;
+
+ len = strlen(buf);
+ if (*(buf + len - 1) != '/') {
+ *(buf + len) = '/';
+ *(buf + len + 1) = 0;
+ }
+
+ strcat(buf, name);
+#if DEBUG
+ syslog(LOG_DEBUG, "statting %s", buf);
+#endif /* DEBUG */
+ if (!stat(buf, &st) && st.st_size)
+ printf("You have %smail.\n",
+ (st.st_mtime > st.st_atime) ? "new " : "");
+ }
+#endif /* !HAVE_MAILCHECK_IN_PROFILE */
+ signal(SIGALRM, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTSTP, SIG_IGN);
+
+ attr.c_lflag |= (ISIG | IEXTEN);
+
+ catchexit();
+ execlp(thisuser.pw_shell, minusnam, 0);
+ perror(thisuser.pw_shell);
+ printf("No shell\n");
+ exit(0);
+}
diff --git a/contrib/opie/opiepasswd.1 b/contrib/opie/opiepasswd.1
new file mode 100644
index 0000000..1fd9123
--- /dev/null
+++ b/contrib/opie/opiepasswd.1
@@ -0,0 +1,176 @@
+.\" opiepasswd.1: Manual page for the opiepasswd(1) program.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Modified by cmetz for OPIE 2.3. Added -f flag documentation.
+.\" Updated console example.
+.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation.
+.\" Modified at NRL for OPIE 2.0.
+.\" Written at Bellcore for the S/Key Version 1 software distribution
+.\" (keyinit.1).
+.\"
+.ll 6i
+.pl 10.5i
+.lt 6.0i
+.TH OPIEPASSWD 1 "January 10, 1995"
+.AT 3
+.SH NAME
+opiepasswd \- Change or set a user's password for the OPIE authentication
+system.
+
+.SH SYNOPSIS
+.B opiepasswd
+[\-v] [\-h] [\-c|\-d] [\-f]
+.sp 0
+[\-n
+.I inital_sequence_number
+]
+[\-s
+.I seed
+] [
+.I user_name
+]
+
+.SH DESCRIPTION
+.I opiepasswd
+will initialize the system information to allow one to use OPIE to login.
+.I opiepasswd
+is downward compatible with the keyinit(1) program from the
+Bellcore S/Key Version 1 distribution.
+
+.SH OPTIONS
+.TP
+.TP
+.B \-v
+Display the version number and compile-time options, then exit.
+.TP
+.B \-h
+Display a brief help message and exit.
+.TP
+.B \-c
+Set console mode where the user is expected to have secure access to the
+system. In console mode, you will be asked to input your password directly
+instead of having to use an OPIE calculator. If you do not have secure access
+to the system (i.e., you are not on the system's console), you are
+volunteering your password to attackers by using this mode.
+.TP
+.B \-d
+Disable OTP logins to the specified account.
+.TP
+.B \-f
+Force
+.I opiepasswd
+to continue, even where it normally shouldn't. This is currently used to
+force opiepasswd to operate in "console" mode even from terminals it believes
+to be insecure. It can also allow users to disclose their secret pass phrases
+to attackers. Use of the -f flag may be disabled by compile-time option in
+your particular build of OPIE.
+.TP
+.B \-n
+Manually specify the initial sequence number. The default is 499.
+.TP
+.B \-s
+Specify a non-random seed. The default is to generate a "random" seed using
+the first two characters of the host name and five pseudo-random digits.
+.SH EXAMPLE
+Using
+.I opiepasswd
+from the console:
+.LP
+.sp 0
+wintermute$ opiepasswd \-c
+.sp 0
+Updating kebe:
+.sp 0
+Reminder \- Only use this method from the console; NEVER from remote. If you
+.sp 0
+are using telnet, xterm, or a dial\-in, type ^C now or exit with no password.
+.sp 0
+Then run opiepasswd without the \-c parameter.
+.sp 0
+Using MD5 to compute responses.
+.sp 0
+Enter old secret pass phrase:
+.sp 0
+Enter new secret pass phrase:
+.sp 0
+Again new secret pass phrase:
+.sp 0
+
+.sp 0
+ID kebe OPIE key is 499 be93564
+.sp 0
+CITE JAN GORY BELA GET ABED
+.sp 0
+wintermute$
+.LP
+Using
+.I opiepasswd
+from remote:
+.LP
+.sp 0
+wintermute$ opiepasswd
+.sp 0
+Updating kebe:
+.sp 0
+Reminder: You need the response from your OPIE calculator.
+.sp 0
+Old secret password:
+.sp 0
+ otp-md5 482 wi93563
+.sp 0
+ Response: FIRM BERN THEE DUCK MANN AWAY
+.sp 0
+New secret password:
+.sp 0
+ otp-md5 499 wi93564
+.sp 0
+ Response: SKY FAN BUG HUFF GUS BEAT
+.sp 0
+
+.sp 0
+ID kebe OPIE key is 499 wi93564
+.sp 0
+SKY FAN BUG HUFF GUS BEAT
+.sp 0
+wintermute$
+.LP
+.SH FILES
+.TP
+/etc/opiekeys -- database of key information for the OPIE system.
+
+.SH SEE ALSO
+.BR passwd (1),
+.BR opie (4),
+.BR opiekey (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8),
+.BR opiekeys (5),
+.BR opieaccess (5)
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opiepasswd.c b/contrib/opie/opiepasswd.c
new file mode 100644
index 0000000..719b68f
--- /dev/null
+++ b/contrib/opie/opiepasswd.c
@@ -0,0 +1,429 @@
+/* opiepasswd.c: Add/change an OTP password in the key database.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Got of some variables and made some
+ local to where they're used. Split out the finishing code. Use
+ opielookup() instead of opiechallenge() to find user. Three
+ strikes on prompts. Use opiepasswd()'s new calling
+ convention. Changed OPIE_PASS_{MAX,MIN} to
+ OPIE_SECRET_{MAX,MIN}. Handle automatic reinits happenning
+ below us. Got rid of unneeded headers. Use new opieatob8()
+ return value convention. Added -f flag. Added SHA support.
+ Modified by cmetz for OPIE 2.22. Finally got rid of the lock
+ filename kluge by implementing refcounts for locks.
+ Use opiepasswd() to update key file. Error if we can't
+ write to the key file. Check for minimum seed length.
+ Modified at NRL for OPIE 2.2. Changed opiestrip_crlf to
+ opiestripcrlf. Check opiereadpass() return value.
+ Minor optimization. Change calls to opiereadpass() to
+ use echo arg. Use opiereadpass() where we can.
+ Make everything static. Ifdef around some headers.
+ Changed use of gethostname() to uname(). Got rid of
+ the need for buf[]. Properly check return value of
+ opieatob8. Check seed length. Always generate proper-
+ length seeds.
+ Modified at NRL for OPIE 2.1. Minor autoconf changes.
+ Modified heavily at NRL for OPIE 2.0.
+ Written at Bellcore for the S/Key Version 1 software distribution
+ (skeyinit.c).
+*/
+#include "opie_cfg.h"
+
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif /* HAVE_PWD_H */
+#include <stdio.h>
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <stdio.h>
+#include <sys/types.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#include "opie.h"
+
+#define MODE_DEFAULT 0
+#define MODE_CONSOLE 1
+#define MODE_DISABLE 2
+
+extern int optind;
+extern char *optarg;
+
+char *algnames[] = { NULL, NULL, NULL, "SHA-1", "MD4", "MD5" };
+char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
+
+static VOIDRET usage FUNCTION((myname), char *myname)
+{
+ fprintf(stderr, "usage: %s [-v] [-h] [-c|-d] [-f] [-n initial_sequence_number]\n [-s seed] [username]\n", myname);
+ exit(1);
+}
+
+static VOIDRET finish FUNCTION((name), char *name)
+{
+ struct opie opie;
+ char buf[OPIE_RESPONSE_MAX + 1];
+
+ if (name) {
+ if (opiechallenge(&opie, name, buf)) {
+ fprintf(stderr, "Error verifying database.\n");
+ finish(NULL);
+ }
+ printf("\nID %s ", opie.opie_principal);
+ if (opie.opie_val && (opie.opie_val[0] == '*')) {
+ printf("is disabled.\n");
+ finish(NULL);
+ }
+ printf("OTP key is %d %s\n", opie.opie_n, opie.opie_seed);
+ {
+ char key[8];
+ if (!opieatob8(key, opie.opie_val)) {
+ fprintf(stderr, "Error verifying key -- possible database corruption.\n");
+ finish(NULL);
+ }
+ printf("%s\n", opiebtoe(buf, key));
+ }
+ }
+
+ while(!opieunlock());
+ exit(name ? 0 : 1);
+}
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ struct opie opie;
+ int rval, n = 499, i, mode = MODE_DEFAULT, force = 0;
+ char seed[18];
+ struct passwd *pp;
+
+ memset(seed, 0, sizeof(seed));
+
+ if (!(pp = getpwuid(getuid()))) {
+ fprintf(stderr, "Who are you?");
+ return 1;
+ }
+
+ while ((i = getopt(argc, argv, "fhvcn:s:")) != EOF) {
+ switch (i) {
+ case 'v':
+ opieversion();
+ case 'f':
+#if INSECURE_OVERRIDE
+ force = 1;
+#else /* INSECURE_OVERRIDE */
+ fprintf(stderr, "Sorry, but the -f option is not supported by this build of OPIE.\n");
+#endif /* INSECURE_OVERRIDE */
+ break;
+ case 'c':
+ mode = MODE_CONSOLE;
+ break;
+ case 'd':
+ mode = MODE_DISABLE;
+ break;
+ case 'n':
+ i = atoi(optarg);
+ if (!(i > 0 && i < 10000)) {
+ printf("Sequence numbers must be > 0 and < 10000\n");
+ finish(NULL);
+ }
+ n = i;
+ break;
+ case 's':
+ i = strlen(optarg);
+ if ((i > OPIE_SEED_MAX) || (i < OPIE_SEED_MIN)) {
+ printf("Seeds must be between %d and %d characters long.\n",
+ OPIE_SEED_MIN, OPIE_SEED_MAX);
+ finish(NULL);
+ }
+ strncpy(seed, optarg, sizeof(seed));
+ seed[sizeof(seed) - 1] = 0;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if (argc - optind >= 1) {
+ if (strcmp(argv[optind], pp->pw_name)) {
+ if (getuid()) {
+ printf("Only root can change others' passwords.\n");
+ exit(1);
+ }
+ if ((pp = getpwnam(argv[optind])) == NULL) {
+ printf("%s: user unknown.\n", argv[optind]);
+ exit(1);
+ }
+ }
+ }
+
+ opielock(pp->pw_name);
+ rval = opielookup(&opie, pp->pw_name);
+
+ switch (rval) {
+ case 0:
+ printf("Updating %s:\n", pp->pw_name);
+ break;
+ case 1:
+ printf("Adding %s:\n", pp->pw_name);
+ break;
+ case 2:
+ fprintf(stderr, "Error: Can't update key database.\n");
+ exit(1);
+ default:
+ fprintf(stderr, "Error reading key database\n");
+ exit(1);
+ }
+
+ if (seed[0]) {
+ i = strlen(seed);
+ if (i > OPIE_SEED_MAX) {
+ fprintf(stderr, "Seeds must be less than %d characters long.", OPIE_SEED_MAX);
+ finish(NULL);
+ }
+ if (i < OPIE_SEED_MIN) {
+ fprintf(stderr, "Seeds must be greater than %d characters long.", OPIE_SEED_MIN);
+ finish(NULL);
+ }
+ } else {
+ if (!rval)
+ strcpy(seed, opie.opie_seed);
+
+ if (opienewseed(seed) < 0) {
+ fprintf(stderr, "Error updating seed.\n");
+ finish(NULL);
+ }
+ }
+
+ if (opie.opie_seed && opie.opie_seed[0] && !strcmp(opie.opie_seed, seed)) {
+ fprintf(stderr, "You must use a different seed for the new OTP sequence.\n");
+ finish(NULL);
+ }
+
+ switch(mode) {
+ case MODE_DEFAULT:
+ {
+ char tmp[OPIE_RESPONSE_MAX + 2];
+
+ printf("You need the response from an OTP generator.\n");
+#if DEBUG
+ if (!rval) {
+#else /* DEBUG */
+ if (!rval && getuid()) {
+#endif /* DEBUG */
+ char oseed[OPIE_SEED_MAX + 1];
+ int on;
+
+ if (opiechallenge(&opie, pp->pw_name, tmp)) {
+ fprintf(stderr, "Error issuing challenge.\n");
+ finish(NULL);
+ }
+ on = opiegetsequence(&opie);
+ {
+ char *c;
+ if (c = strrchr(tmp, ' '))
+ strncpy(oseed, c + 1, sizeof(oseed));
+ else {
+#if DEBUG
+ fprintf(stderr, "opiepasswd: bogus challenge\n");
+#endif /* DEBUG */
+ finish(NULL);
+ }
+ }
+ printf("Old secret pass phrase:\n\t%s\n\tResponse: ", tmp);
+ if (!opiereadpass(tmp, sizeof(tmp), 1))
+ tmp[0] = 0;
+ i = opieverify(&opie, tmp);
+ if (!tmp[0]) {
+ fprintf(stderr, "Error reading response.\n");
+ finish(NULL);
+ }
+ if (i) {
+ fprintf(stderr, "Error verifying response.\n");
+#if DEBUG
+ fprintf(stderr, "opiepasswd: opieverify() returned %d\n", i);
+#endif /* DEBUG */
+ finish(NULL);
+ }
+ {
+ char nseed[OPIE_SEED_MAX + 1];
+ int nn;
+
+ if (opiechallenge(&opie, pp->pw_name, tmp)) {
+ fprintf(stderr, "Error verifying database.\n");
+ finish(NULL);
+ }
+
+ nn = opiegetsequence(&opie);
+ {
+ char *c;
+ if (c = strrchr(tmp, ' '))
+ strncpy(nseed, c + 1, sizeof(nseed));
+ else {
+#if DEBUG
+ fprintf(stderr, "opiepasswd: bogus challenge\n");
+#endif /* DEBUG */
+ finish(NULL);
+ }
+ }
+
+ opieverify(&opie, "");
+ nn++;
+
+ if ((nn != on) || strcmp(oseed, nseed))
+ finish(pp->pw_name);
+ }
+ }
+ printf("New secret pass phrase:");
+ for (i = 0;; i++) {
+ if (i > 2)
+ finish(NULL);
+ printf("\n\totp-%s %d %s\n\tResponse: ", algids[MDX], n, seed);
+ if (!opiereadpass(tmp, sizeof(tmp), 1)) {
+ fprintf(stderr, "Error reading response.\n");
+ finish(NULL);
+ }
+ if (tmp[0] == '?') {
+ printf("Enter the response from your OTP calculator: \n");
+ continue;
+ }
+ if (tmp[0] == '\0') {
+ fprintf(stderr, "Secret pass phrase unchanged.\n");
+ finish(NULL);
+ }
+
+ if (!(rval = opiepasswd(&opie, 0, pp->pw_name, n, seed, tmp)))
+ finish(pp->pw_name);
+
+ if (rval < 0) {
+ fprintf(stderr, "Error updating key database.\n");
+ finish(NULL);
+ }
+ printf("\tThat is not a valid OTP response.\n");
+ }
+ }
+ break;
+ case MODE_CONSOLE:
+ {
+ char passwd[OPIE_SECRET_MAX + 1], passwd2[OPIE_SECRET_MAX + 1];
+ /* Get user's secret password */
+ fprintf(stderr, "Only use this method from the console; NEVER from remote. If you are using\n");
+ fprintf(stderr, "telnet, xterm, or a dial-in, type ^C now or exit with no password.\n");
+ fprintf(stderr, "Then run opiepasswd without the -c parameter.\n");
+ if (opieinsecure()) {
+ fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n");
+ if (force)
+ fprintf(stderr, "Warning: Continuing could disclose your secret pass phrase to an attacker!\n");
+ else
+ finish(NULL);
+ };
+ printf("Using %s to compute responses.\n", algnames[MDX]);
+ if (!rval && getuid()) {
+ printf("Enter old secret pass phrase: ");
+ if (!opiereadpass(passwd, sizeof(passwd), 0)) {
+ fprintf(stderr, "Error reading secret pass phrase!\n");
+ finish(NULL);
+ }
+ if (!passwd[0]) {
+ fprintf(stderr, "Secret pass phrase unchanged.\n");
+ finish(NULL);
+ }
+ {
+ char key[8];
+ char tbuf[OPIE_RESPONSE_MAX + 1];
+
+ if (opiekeycrunch(MDX, key, opie.opie_seed, passwd) != 0) {
+ fprintf(stderr, "%s: key crunch failed. Secret pass phrase unchanged\n", argv[0]);
+ finish(NULL);
+ }
+ memset(passwd, 0, sizeof(passwd));
+ i = opie.opie_n - 1;
+ while (i-- != 0)
+ opiehash(key, MDX);
+ opiebtoe(tbuf, key);
+ if (opieverify(&opie, tbuf)) {
+ fprintf(stderr, "Sorry.\n");
+ finish(NULL);
+ }
+ }
+ }
+ for (i = 0;; i++) {
+ if (i > 2)
+ finish(NULL);
+ printf("Enter new secret pass phrase: ");
+ if (!opiereadpass(passwd, sizeof(passwd), 0)) {
+ fprintf(stderr, "Error reading secret pass phrase.\n");
+ finish(NULL);
+ }
+ if (!passwd[0] || feof(stdin)) {
+ fprintf(stderr, "Secret pass phrase unchanged.\n");
+ finish(NULL);
+ }
+ if (opiepasscheck(passwd)) {
+ memset(passwd, 0, sizeof(passwd));
+ fprintf(stderr, "Secret pass phrases must be between %d and %d characters long.\n", OPIE_SECRET_MIN, OPIE_SECRET_MAX);
+ continue;
+ }
+ printf("Again new secret pass phrase: ");
+ if (!opiereadpass(passwd2, sizeof(passwd2), 0)) {
+ fprintf(stderr, "Error reading secret pass phrase.\n");
+ finish(NULL);
+ }
+ if (feof(stdin)) {
+ fprintf(stderr, "Secret pass phrase unchanged.\n");
+ finish(NULL);
+ }
+ if (!passwd[0] || !strcmp(passwd, passwd2))
+ break;
+ fprintf(stderr, "Sorry, no match.\n");
+ }
+ memset(passwd2, 0, sizeof(passwd2));
+ if (opiepasswd(&opie, 1, pp->pw_name, n, seed, passwd)) {
+ fprintf(stderr, "Error updating key database.\n");
+ finish(NULL);
+ }
+ finish(pp->pw_name);
+ }
+ case MODE_DISABLE:
+ {
+ char tmp[4];
+ int i;
+
+ for (i = 0;; i++) {
+ if (i > 2)
+ finish(NULL);
+
+ printf("Disable %s's OTP access? (yes or no) ", pp->pw_name);
+ if (!opiereadpass(tmp, sizeof(tmp), 1)) {
+ fprintf(stderr, "Error reading entry.\n");
+ finish(NULL);
+ }
+ if (!strcmp(tmp, "no"))
+ finish(NULL);
+ if (!strcmp(tmp, "yes")) {
+ if (opiepasswd(&opie, 0, pp->pw_name, n, seed, NULL)) {
+ fprintf(stderr, "Error updating key database.\n");
+ finish(NULL);
+ }
+ finish(pp->pw_name);
+ }
+ }
+ }
+ }
+}
diff --git a/contrib/opie/opieserv.1 b/contrib/opie/opieserv.1
new file mode 100644
index 0000000..edde9eb
--- /dev/null
+++ b/contrib/opie/opieserv.1
@@ -0,0 +1,82 @@
+.\" opieserv.1: Manual page for the opieserv(1) program.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Created by cmetz for OPIE 2.2 from opiegen.1.
+.\"
+.ll 6i
+.pl 10.5i
+.lt 6.0i
+.TH OPIEKEY 1 "February 20, 1996"
+.AT 3
+.SH NAME
+opieserv \- Example OPIE-based OTP server
+
+.SH SYNOPSIS
+.B opieserv
+.sp 0
+[
+.I principal
+]
+.sp 0
+
+.SH DESCRIPTION
+.I opieserv
+takes an OTP principal (e.g., a user name) from either the command line or
+standard input and returns a current OTP challenge for that principal. It then
+reads an OTP response to that challenge from standard input and displays a
+message and returns a value to indicate either success (exit value = 0) or
+failure (exit value = 1). It is intended as an example for programmers
+of how a simple OTP server can be built.
+
+.SH EXAMPLE
+.sp 0
+wintermute$ opieserv kebe
+.sp 0
+otp-md5 495 wi01309
+.sp 0
+Response:
+.sp 0
+User verified.
+.sp 0
+wintermute$
+.LP
+
+.SH SEE ALSO
+.BR opiegen (1),
+.BR opiekey (1),
+.BR opie (4),
+.BR opiepasswd (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8),
+.BR opiekeys (5),
+.BR opieaccess (5)
+
+.SH AUTHOR
+The opieserv1) program was created by Craig Metz for OPIE 2.2.
+
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opieserv.c b/contrib/opie/opieserv.c
new file mode 100644
index 0000000..241dbb3
--- /dev/null
+++ b/contrib/opie/opieserv.c
@@ -0,0 +1,83 @@
+/* opieserv.c: Sample OTP server based on the opiechallenge() and
+ opieverify() library routines.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Send debug info to syslog.
+ Created by cmetz for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#include <stdio.h>
+#if DEBUG
+#include <syslog.h>
+#endif /* DEBUG */
+#include "opie.h"
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ struct opie opie;
+ char *principal;
+ char buffer[1024];
+ char challenge[OPIE_CHALLENGE_MAX+1];
+ char response[OPIE_RESPONSE_MAX+1];
+ int result;
+
+ if (argc <= 1) {
+ fputs("Principal: ", stderr);
+ if (!opiereadpass(buffer, sizeof(buffer)-1, 1))
+ fprintf(stderr, "Error reading principal!");
+ principal = buffer;
+ } else {
+ principal = argv[1];
+ }
+#if DEBUG
+ syslog(LOG_DEBUG, "Principal is +%s+", principal);
+#endif /* DEBUG */
+
+ switch (result = opiechallenge(&opie, principal, challenge)) {
+ case -1:
+ fputs("System error!\n", stderr);
+ exit(1);
+ case 0:
+ break;
+ case 1:
+ fputs("User not found!\n", stderr);
+ exit(1);
+ case 2:
+ fputs("System error!\n", stderr);
+ exit(1);
+ default:
+ fprintf(stderr, "Unknown error %d!\n", result);
+ exit(1);
+ };
+
+ fputs(challenge, stdout);
+ fputc('\n', stdout);
+ fflush(stdout);
+ fputs("Response: ", stderr);
+ if (!opiereadpass(response, OPIE_RESPONSE_MAX, 1)) {
+ fputs("Error reading response!\n", stderr);
+ exit(1);
+ };
+
+ switch (result = opieverify(&opie, response)) {
+ case -1:
+ fputs("System error!\n", stderr);
+ exit(1);
+ case 0:
+ fputs("User verified.\n", stderr);
+ exit(0);
+ case 1:
+ fputs("Verify failed!\n", stderr);
+ exit(1);
+ default:
+ fprintf(stderr, "Unknown error %d!\n", result);
+ exit(1);
+ }
+}
diff --git a/contrib/opie/opiesu.1 b/contrib/opie/opiesu.1
new file mode 100644
index 0000000..5edf24b
--- /dev/null
+++ b/contrib/opie/opiesu.1
@@ -0,0 +1,101 @@
+.\" opiesu.c: Manual page for the opiesu(1) program.
+.\"
+.\" %%% portions-copyright-cmetz
+.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights
+.\" Reserved. The Inner Net License Version 2 applies to these portions of
+.\" the software.
+.\" You should have received a copy of the license with this software. If
+.\" you didn't get a copy, you may request one from <license@inner.net>.
+.\"
+.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned
+.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+.\" License Agreement applies to this software.
+.\"
+.\" History:
+.\"
+.\" Modified by cmetz for OPIE 2.3. Removed statement that opiesu will
+.\" only accept OTP responses.
+.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation.
+.\" Modified at NRL for OPIE 2.0.
+.\" Documentation for the "-f" option from BSD.
+.\" Written at Bellcore for the S/Key Version 1 software distribution
+.\" (keysu.1).
+.\"
+.ll 6i
+.pl 10.5i
+.lt 6.0i
+.TH OPIESU 1 "January 10, 1995"
+.AT 3
+.SH NAME
+opiesu \- Replacement su(1) program that uses OPIE challenges
+.SH SYNOPSIS
+.B opiesu
+[ \-f ] [ \-c ] [
+.I user_name
+]
+.SH DESCRIPTION
+.I opiesu
+is a replacement for the su(1) program that issues OPIE challenges and
+uses OPIE responses. It is downward compatible with keysu(1) from the
+Bellcore S/Key Version 1 distribution and the su(1) program from the 4.3BSD
+Net/2 distribution.
+.SH OPTIONS
+.TP
+.B \-f
+If the invoked shell is csh(1), this option prevents it from
+reading the ``.cshrc'' file. (The [f] option may be passed as a
+shell argument after the login name, so this option is redundant
+and obsolescent.)
+.TP
+.B \-c
+Set console mode where the user is expected to have secure access to the
+system. In console mode, you will be asked to input your password directly
+instead of having to use an OPIE calculator. If you do not have secure access
+to the system (i.e., you are not on the system's console), you are
+volunteering your password to attackers by using this mode.
+.TP
+.I user_name
+The name of the user to become.
+The default is root.
+.SH EXAMPLE
+.sp 0
+wintermute$ opiesu kebe
+.sp 0
+otp-md5 498 wi910502
+.sp 0
+(OTP response required)
+.sp 0
+kebe's password: (echo on)
+.sp 0
+kebe's password: RARE GLEN HUGH BOYD NECK MOLL
+.sp 0
+wintermute#
+.LP
+.SH FILES
+.TP
+/etc/opiekeys database of information for OPIE system.
+.LP
+.SH SEE ALSO
+.BR su (1),
+.BR opie (4),
+.BR opiekey (1),
+.BR opieinfo (1),
+.BR opiesu (1),
+.BR opielogin (1),
+.BR opieftpd (8),
+.BR opiekeys (5),
+.BR opieaccess (5)
+
+.SH AUTHOR
+Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden
+of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and
+Craig Metz.
+
+S/Key is a trademark of Bell Communications Research (Bellcore).
+
+.SH CONTACT
+OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join,
+send an email request to:
+.sp
+skey-users-request@thumper.bellcore.com
diff --git a/contrib/opie/opiesu.c b/contrib/opie/opiesu.c
new file mode 100644
index 0000000..403305b
--- /dev/null
+++ b/contrib/opie/opiesu.c
@@ -0,0 +1,448 @@
+/* opiesu.c: main body of code for the su(1m) program
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Limit the length of TERM on full login.
+ Use HAVE_SULOG instead of DOSULOG.
+ Modified by cmetz for OPIE 2.2. Don't try to clear non-blocking I/O.
+ Use opiereadpass(). Minor speedup. Removed termios manipulation
+ -- that's opiereadpass()'s job. Change opiereadpass() calls
+ to add echo arg. Removed useless strings (I don't think that
+ removing the ucb copyright one is a problem -- please let me
+ know if I'm wrong). Use FUNCTION declaration et al. Ifdef
+ around some headers. Make everything static. Removed
+ closelog() prototype. Use the same catchexit() trickery as
+ opielogin.
+ Modified at NRL for OPIE 2.2. Changed opiestrip_crlf to
+ opiestripcrlf.
+ Modified at NRL for OPIE 2.1. Added struct group declaration.
+ Added Solaris(+others?) sulog capability. Symbol changes
+ for autoconf. Removed des_crypt.h. File renamed to
+ opiesu.c. Symbol+misc changes for autoconf. Added bletch
+ for setpriority.
+ Modified at NRL for OPIE 2.02. Added SU_STAR_CHECK (turning a bug
+ into a feature ;). Fixed Solaris shadow password problem
+ introduced in OPIE 2.01 (the shadow password structure is
+ spwd, not spasswd).
+ Modified at NRL for OPIE 2.01. Changed password lookup handling
+ to use a static structure to avoid problems with drain-
+ bamaged shadow password packages. Always log failures.
+ Make sure to close syslog by function to avoid problems
+ with drain bamaged syslog implementations. Log a few
+ interesting errors.
+ Modified at NRL for OPIE 2.0.
+ Modified at Bellcore for the S/Key Version 1 software distribution.
+ Originally from BSD.
+*/
+
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#include "opie_cfg.h"
+
+#include <stdio.h>
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif /* HAVE_PWD_H */
+#include <grp.h>
+#include <syslog.h>
+#include <sys/types.h>
+#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else /* TIME_WITH_SYS_TIME */
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else /* HAVE_SYS_TIME_H */
+#include <time.h>
+#endif /* HAVE_SYS_TIME_H */
+#endif /* TIME_WITH_SYS_TIME */
+#include <sys/resource.h>
+#else /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
+#if TM_IN_SYS_TIME
+#include <sys/time.h>
+#else /* TM_IN_SYS_TIME */
+#include <time.h>
+#endif /* TM_IN_SYS_TIME */
+#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <errno.h>
+
+#include "opie.h"
+
+static char userbuf[16] = "USER=";
+static char homebuf[128] = "HOME=";
+static char shellbuf[128] = "SHELL=";
+static char pathbuf[128] = "PATH=";
+static char termbuf[32] = "TERM=";
+static char *cleanenv[] = {userbuf, homebuf, shellbuf, pathbuf, 0, 0};
+static char *user = "root";
+static char *shell = "/bin/sh";
+static int fulllogin;
+static int fastlogin;
+
+extern char **environ;
+static struct passwd thisuser, nouser;
+
+#if HAVE_SHADOW_H
+#include <shadow.h>
+#endif /* HAVE_SHADOW_H */
+
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif /* HAVE_CRYPT_H */
+
+static VOIDRET catchexit FUNCTION_NOARGS
+{
+ int i;
+ closelog();
+ for (i = sysconf(_SC_OPEN_MAX); i > 2; i--)
+ close(i);
+}
+
+/* We allow the malloc()s to potentially leak data out because we can
+only call this routine about four times in the lifetime of this process
+and the kernel will free all heap memory when we exit or exec. */
+static int lookupuser FUNCTION((name), char *name)
+{
+ struct passwd *pwd;
+#if HAVE_SHADOW
+ struct spwd *spwd;
+#endif /* HAVE_SHADOW */
+
+ memcpy(&thisuser, &nouser, sizeof(thisuser));
+
+ if (!(pwd = getpwnam(name)))
+ return -1;
+
+ thisuser.pw_uid = pwd->pw_uid;
+ thisuser.pw_gid = pwd->pw_gid;
+
+ if (!(thisuser.pw_name = malloc(strlen(pwd->pw_name) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_name, pwd->pw_name);
+
+ if (!(thisuser.pw_dir = malloc(strlen(pwd->pw_dir) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_dir, pwd->pw_dir);
+
+ if (!(thisuser.pw_shell = malloc(strlen(pwd->pw_shell) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_shell, pwd->pw_shell);
+
+#if HAVE_SHADOW
+ if (!(spwd = getspnam(name)))
+ goto lookupuserbad;
+
+ pwd->pw_passwd = spwd->sp_pwdp;
+
+ endspent();
+#endif /* HAVE_SHADOW */
+
+ if (!(thisuser.pw_passwd = malloc(strlen(pwd->pw_passwd) + 1)))
+ goto lookupuserbad;
+ strcpy(thisuser.pw_passwd, pwd->pw_passwd);
+
+ endpwent();
+
+#if SU_STAR_CHECK
+ return ((thisuser.pw_passwd[0] == '*') || (thisuser.pw_passwd[0] == '#'));
+#else /* SU_STAR_CHECK */
+ return 0;
+#endif /* SU_STAR_CHECK */
+
+lookupuserbad:
+ memcpy(&thisuser, &nouser, sizeof(thisuser));
+ return -1;
+}
+
+static VOIDRET lsetenv FUNCTION((ename, eval, buf), char *ename AND char *eval AND char *buf)
+{
+ register char *cp, *dp;
+ register char **ep = environ;
+
+ /* this assumes an environment variable "ename" already exists */
+ while (dp = *ep++) {
+ for (cp = ename; *cp == *dp && *cp; cp++, dp++)
+ continue;
+ if (*cp == 0 && (*dp == '=' || *dp == 0)) {
+ strcat(buf, eval);
+ *--ep = buf;
+ return;
+ }
+ }
+}
+
+#if HAVE_SULOG
+static int sulog FUNCTION((status, who), int status AND char *who)
+{
+ char *from;
+ char *ttynam;
+ struct tm *tm;
+ FILE *f;
+ time_t now;
+
+ if (who)
+ from = who;
+ else
+ from = Getlogin();
+
+ if (!strncmp(ttynam = ttyname(2), "/dev/", 5))
+ ttynam += 5;
+
+ now = time(NULL);
+ tm = localtime(&now);
+
+ if (!(f = fopen("/var/adm/sulog", "a"))) {
+ fprintf(stderr, "Can't update su log!\n");
+ exit(1);
+ }
+
+ fprintf(f, "SU %02d/%02d %02d:%02d %c %s %s-%s\n",
+ tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ result ? '+' : '-', ttynam, from, user);
+ fclose(f);
+}
+#endif /* HAVE_SULOG */
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ char buf[1000], *p;
+ struct opie opie;
+ int i;
+ char pbuf[256];
+ char opieprompt[80];
+ int console = 0;
+
+#define Getlogin() (((p = getlogin()) && *p) ? p : buf)
+
+ for (i = sysconf(_SC_OPEN_MAX); i > 2; i--)
+ close(i);
+
+ strcat(pathbuf, DEFAULT_PATH);
+
+again:
+ if (argc > 1 && strcmp(argv[1], "-f") == 0) {
+ fastlogin++;
+ argc--, argv++;
+ goto again;
+ }
+ if (argc > 1 && strcmp(argv[1], "-c") == 0) {
+ console++;
+ argc--, argv++;
+ goto again;
+ }
+ if (argc > 1 && strcmp(argv[1], "-") == 0) {
+ fulllogin++;
+ argc--;
+ argv++;
+ goto again;
+ }
+ if (argc > 1 && argv[1][0] != '-') {
+ user = argv[1];
+ argc--;
+ argv++;
+ }
+
+ openlog("su", LOG_ODELAY, LOG_AUTH);
+ atexit(catchexit);
+
+ {
+ struct passwd *pwd;
+
+ if ((pwd = getpwuid(getuid())) == NULL) {
+ syslog(LOG_CRIT, "'%s' failed for unknown uid %d on %s", argv[0], getuid(), ttyname(2));
+#if HAVE_SULOG
+ sulog(0, "unknown");
+#endif /* HAVE_SULOG */
+ exit(1);
+ }
+ strcpy(buf, pwd->pw_name);
+ }
+
+ if (lookupuser(user)) {
+ syslog(LOG_CRIT, "'%s' failed for %s on %s", argv[0], Getlogin(), ttyname(2));
+#if HAVE_SULOG
+ sulog(0, NULL);
+#endif /* HAVE_SULOG */
+ fprintf(stderr, "Unknown user: %s\n", user);
+ exit(1);
+ }
+
+/* Implement the BSD "wheel group" su restriction. */
+#if DOWHEEL
+ /* Only allow those in group zero to su to root? */
+ if (thisuser.pw_uid == 0) {
+ struct group *gr;
+ if ((gr = getgrgid(0)) != NULL) {
+ for (i = 0; gr->gr_mem[i] != NULL; i++)
+ if (strcmp(buf, gr->gr_mem[i]) == 0)
+ goto userok;
+ fprintf(stderr, "You do not have permission to su %s\n", user);
+ exit(1);
+ }
+userok:
+ ;
+#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H
+ setpriority(PRIO_PROCESS, 0, -2);
+#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
+ }
+#endif /* DOWHEEL */
+
+ if (!thisuser.pw_passwd[0] || getuid() == 0)
+ goto ok;
+
+ if (console) {
+ if (!opiealways(thisuser.pw_dir)) {
+ fprintf(stderr, "That account requires OTP responses.\n");
+ exit(1);
+ };
+ /* Get user's secret password */
+ fprintf(stderr, "Reminder - Only use this method from the console; NEVER from remote. If you\n");
+ fprintf(stderr, "are using telnet, xterm, or a dial-in, type ^C now or exit with no password.\n");
+ fprintf(stderr, "Then run su without the -c parameter.\n");
+ if (opieinsecure()) {
+ fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n");
+ exit(1);
+ };
+#if NEW_PROMPTS
+ printf("%s's system password: ", thisuser.pw_name);
+ if (!opiereadpass(pbuf, sizeof(pbuf), 0))
+ goto error;
+#endif /* NEW_PROMPTS */
+ } else {
+ /* Attempt an OTP challenge */
+ i = opiechallenge(&opie, user, opieprompt);
+ printf("%s\n", opieprompt);
+#if NEW_PROMPTS
+ printf("%s's response: ", thisuser.pw_name);
+ if (!opiereadpass(pbuf, sizeof(pbuf), 1))
+ goto error;
+#else /* NEW_PROMPTS */
+ printf("(OTP response required)\n");
+#endif /* NEW_PROMPTS */
+ fflush(stdout);
+ };
+#if !NEW_PROMPTS
+ printf("%s's password: ", thisuser.pw_name);
+ if (!opiereadpass(pbuf, sizeof(pbuf), 0))
+ goto error;
+#endif /* !NEW_PROMPTS */
+
+#if !NEW_PROMPTS
+ if (!pbuf[0] && !console) {
+ /* Null line entered; turn echoing back on and read again */
+ printf(" (echo on)\n%s's password: ", thisuser.pw_name);
+ if (!opiereadpass(pbuf, sizeof(pbuf), 1))
+ goto error;
+ }
+#endif /* !NEW_PROMPTS */
+
+ if (console) {
+ /* Try regular password check, if allowed */
+ if (!strcmp(crypt(pbuf, thisuser.pw_passwd), thisuser.pw_passwd))
+ goto ok;
+ } else {
+ int i = opiegetsequence(&opie);
+ if (!opieverify(&opie, pbuf)) {
+ /* OPIE authentication succeeded */
+ if (i < 5)
+ fprintf(stderr, "Warning: Change %s's OTP secret pass phrase NOW!\n", user);
+ else
+ if (i < 10)
+ fprintf(stderr, "Warning: Change %s's OTP secret pass phrase soon.\n", user);
+ goto ok;
+ };
+ };
+error:
+ opieverify(&opie, "");
+ fprintf(stderr, "Sorry\n");
+ syslog(LOG_CRIT, "'%s' failed for %s on %s", argv[0], Getlogin(), ttyname(2));
+#if HAVE_SULOG
+ sulog(0, NULL);
+#endif /* HAVE_SULOG */
+ exit(2);
+
+ok:
+ syslog(LOG_NOTICE, "'%s' by %s on %s", argv[0], Getlogin(), ttyname(2));
+#if HAVE_SULOG
+ sulog(1, NULL);
+#endif /* HAVE_SULOG */
+
+ if (setgid(thisuser.pw_gid) < 0) {
+ perror("su: setgid");
+ exit(3);
+ }
+ if (initgroups(user, thisuser.pw_gid)) {
+ fprintf(stderr, "su: initgroups failed (errno=%d)\n", errno);
+ exit(4);
+ }
+ if (setuid(thisuser.pw_uid) < 0) {
+ perror("su: setuid");
+ exit(5);
+ }
+ if (thisuser.pw_shell && *thisuser.pw_shell)
+ shell = thisuser.pw_shell;
+ if (fulllogin) {
+ if (p = getenv("TERM")) {
+ strncpy(termbuf, p, sizeof(termbuf));
+ cleanenv[4] = termbuf;
+ }
+ environ = cleanenv;
+ }
+ if (fulllogin || strcmp(user, "root") != 0)
+ lsetenv("USER", thisuser.pw_name, userbuf);
+ lsetenv("SHELL", shell, shellbuf);
+ lsetenv("HOME", thisuser.pw_dir, homebuf);
+
+#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H
+ setpriority(PRIO_PROCESS, 0, 0);
+#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
+
+ if (fastlogin) {
+ *argv-- = "-f";
+ *argv = "su";
+ } else
+ if (fulllogin) {
+ if (chdir(thisuser.pw_dir) < 0) {
+ fprintf(stderr, "No directory\n");
+ exit(6);
+ }
+ *argv = "-su";
+ } else {
+ *argv = "su";
+ }
+
+ catchexit();
+
+#if DEBUG
+ syslog(LOG_DEBUG, "execing %s", shell);
+#endif /* DEBUG */
+ execv(shell, argv);
+ fprintf(stderr, "No shell\n");
+ exit(7);
+}
diff --git a/contrib/opie/opietest.c b/contrib/opie/opietest.c
new file mode 100644
index 0000000..edccf74
--- /dev/null
+++ b/contrib/opie/opietest.c
@@ -0,0 +1,255 @@
+/* opietest.c: Quick, though definitely not complete, regression test for
+ libopie. This is intended to catch two things:
+
+ (1) when changes break something
+ (2) if some system wierdness (libc, compiler, or CPU/hardware) is
+ not getting along at all with OPIE.
+
+ It's safe to say that, if tests fail, OPIE isn't going to work right
+on your system. The converse is not such a safe statement.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Use new calling conventions for
+ opiebtoa8()/atob8(). opiegenerator() outputs hex now.
+ Modified by cmetz for OPIE 2.22. Test opielock()/opieunlock()
+ refcount support.
+ Created by cmetz for OPIE 2.2.
+*/
+#include "opie_cfg.h"
+#include <stdio.h>
+#include "opie.h"
+
+char buffer[1024];
+int tests_passed = 0;
+int tests_failed = 0;
+int ntests = 0, testn = 0;
+
+int testatob8()
+{
+ static char testin[] = "0123456789abcdef";
+ static unsigned char testout[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+
+ if (!opieatob8(buffer, testin))
+ return -1;
+
+ if (memcmp(buffer, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testbtoa8()
+{
+ static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ static char testout[] = "0123456789abcdef";
+
+ if (!opiebtoa8(buffer, testin))
+ return -1;
+
+ if (memcmp(buffer, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testbtoe()
+{
+ static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ static char testout[] = "AIM HEW BLUM FED MITE WARM";
+
+ if (!opiebtoe(buffer, testin))
+ return -1;
+
+ if (memcmp(buffer, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testetob()
+{
+ static char testin[] = "AIM HEW BLUM FED MITE WARM";
+ static unsigned char testout[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+
+ if (opieetob(buffer, testin) != 1)
+ return -1;
+
+ if (memcmp(buffer, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testgenerator()
+{
+ static char testin1[] = "otp-md5 123 ke1234";
+ static char testin2[] = "this is a test";
+ /* static char testout[] = "END KERN BALM NICK EROS WAVY"; */
+ static char testout[] = "11D4 C147 E227 C1F1";
+
+ if (opiegenerator(testin1, testin2, buffer))
+ return -1;
+
+ if (memcmp(buffer, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testgetsequence()
+{
+ struct opie testin;
+ testin.opie_n = 42;
+
+ if (opiegetsequence(&testin) != 42)
+ return -1;
+
+ return 0;
+}
+
+int testhashmd4()
+{
+ static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ static unsigned char testout[] = { 0x9f, 0x40, 0xfb, 0x84, 0xb, 0xf8, 0x7f, 0x4b };
+
+ opiehash(testin, 4);
+
+ if (memcmp(testin, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testhashmd5()
+{
+ static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ static unsigned char testout[] = { 0x78, 0xdd, 0x1a, 0x37, 0xf8, 0x91, 0x54, 0xe1 };
+
+ opiehash(testin, 5);
+
+ if (memcmp(testin, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testkeycrunch()
+{
+ static char testin1[] = "ke1234";
+ static char testin2[] = "this is a test";
+ static unsigned char testout[] = { 0x2e, 0xd3, 0x5d, 0x74, 0x3e, 0xa9, 0xe9, 0xe8 };
+
+ if (opiekeycrunch(5, buffer, testin1, testin2))
+ return -1;
+
+ if (memcmp(buffer, testout, sizeof(testout)))
+ return -1;
+
+ return 0;
+}
+
+int testlock()
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ if (opielock("__opietest"))
+ return -1;
+
+ return 0;
+}
+
+int testpasscheck()
+{
+ static char testin1[] = "abadone";
+ static char testin2[] = "A more reasonable choice.";
+
+ if (!opiepasscheck(testin1))
+ return -1;
+
+ if (opiepasscheck(testin2))
+ return -1;
+
+ return 0;
+}
+
+int testunlock()
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ if (opieunlock())
+ return -1;
+
+ if (opieunlock() != -1)
+ return -1;
+
+ return 0;
+}
+
+struct opietest {
+ int (*f)();
+ char *n;
+};
+
+static struct opietest opietests[] = {
+ { testatob8, "atob8" },
+ { testbtoa8, "btoa8" },
+ { testbtoe, "btoe" },
+ { testetob, "etob" },
+/* { testchallenge, "challenge" }, */
+ { testgenerator, "generator" },
+ { testgetsequence, "getsequence" },
+/* { testgetutmpentry, "getutmpentry" }, */
+ { testhashmd4, "hash(MD4)" },
+ { testhashmd5, "hash(MD5)" },
+/* { testinsecure, "insecure" }, */
+ { testkeycrunch, "keycrunch" },
+ { testlock, "lock" },
+/* { testpututmpentry, "pututmpentry" }, */
+/* { testrandomchallenge, "randomchallenge" }, */
+/* { testreadpass, "readpass" }, */
+ { testunlock, "unlock" },
+/* { testverify, "verify" }, */
+/* { testversion, "version" }, */
+ { NULL, NULL }
+};
+
+int main FUNCTION((argc, argv), int argc AND char *argv[])
+{
+ struct opietest *opietest;
+
+ for (opietest = opietests; opietest->n; opietest++)
+ ntests++;
+
+ printf("opietest: executing %d tests\n", ntests);
+
+ for (opietest = opietests, testn = 1; opietest->n; opietest++) {
+ printf("(%2d/%2d) testing opie%s... ", testn++, ntests, opietest->n);
+ if (opietest->f()) {
+ printf("FAILED!\n");
+ tests_failed++;
+ } else {
+ printf("passed\n");
+ tests_passed++;
+ opietest->f = NULL;
+ }
+ }
+
+ printf("opietest: completed %d tests. %d tests passed, %d tests failed.\n", ntests, tests_passed, tests_failed);
+ if (tests_failed) {
+ printf("opietest: please correct the following failures before attempting to use OPIE:\n");
+ for (opietest = opietests; opietest->n; opietest++)
+ if (opietest->f)
+ printf(" opie%s\n", opietest->n);
+ exit(1);
+ }
+ exit(0);
+}
diff --git a/contrib/opie/options.h b/contrib/opie/options.h
new file mode 100644
index 0000000..05f1e55
--- /dev/null
+++ b/contrib/opie/options.h
@@ -0,0 +1,85 @@
+/* options.h: Configuration options the end user might want to tweak.
+
+%%% copyright-cmetz
+This software is Copyright 1996 by Craig Metz, All Rights Reserved.
+The Inner Net License Version 2 applies to this software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+ History:
+
+ Created by cmetz for OPIE 2.3 using the old Makefile.source as a
+ guide.
+*/
+/*
+ Which hash should the OPIE server software use?
+
+ We strongly recommend that you use MD5. MD4 is faster, but less secure.
+If you are migrating from Bellcore S/Key version 1 and wish to use the
+existing key database, you must use MD4. In this case, you should consider
+ways to re-key your users using MD5.
+*/
+
+#define MDX 5 /* Use MD5 */
+/* #define MDX 4 /* Use MD4 */
+
+/*
+ Ask users to re-type their secret pass phrases?
+
+ Doing so helps catch typing mistakes, but some users find it annoying.
+*/
+
+/* #define RETYPE 1 /* Ask users to re-type their secret pass phrases */
+#define RETYPE 0 /* Don't ask users to re-type their secret pass phrases */
+
+/*
+ Generater lock files to serialize OTP logins?
+
+ There is a potential race attack on OTP when more than one session can
+respond to the same challenge at the same time. This locking only allows
+one session at a time per principal (user) to attempt to log in using OTP.
+The locking, however, creates a denial-of-service attack as a trade-off and
+can be annoying if you have a legitimate need for two sessions to attempt
+to authenticate as the same principal at the same time.
+*/
+
+#define USER_LOCKING 1 /* Serialize OTP challenges for a principal */
+/* #define USER_LOCKING 0 /* Don't serialize OTP challenges */
+
+/*
+ Should su(8) refuse to switch to disabled accounts?
+
+ Traditionally, su(8) can switch to any account, even if it is disabled.
+In most systems, there is no legitimate need for this capability and it can
+create security problems.
+*/
+
+#define SU_STAR_CHECK 1 /* Refuse to switch to disabled accounts */
+/* #define SU_STAR_CHECK 0 /* Allow switching to disabled accounts */
+
+/*
+ Should OPIE use more informative prompts?
+
+ The new-style, more informative prompts better indicate to the user what
+is being asked for. However, some automated login scripts depend on the
+wording of some prompts and will fail if you change them.
+*/
+
+#define NEW_PROMPTS 1 /* Use the more informative prompts */
+/* #define NEW_PROMPTS 0 /* Use the more compatible prompts */
+
+/*
+ Should the user be allowed to override "insecure" terminal checks?
+
+ The "insecure" terminal checks are designed to help make it more clear
+to users that they shouldn't disclose their secret over insecure lines
+by refusing to accept the secret directly. These checks aren't perfect and
+sometimes will cause OPIE to refuse to work when it really should. Allowing
+users to override the terminal checks also helps the process of creating
+OTP sequences for users. However, allowing users to override the terminal
+checks also allows users to shoot themselves in the foot, which isn't usually
+what you want.
+*/
+
+#define INSECURE_OVERRIDE 0 /* Don't allow users to override the checks */
+/* #define INSECURE_OVERRIDE 1 /* Allow users to override the checks */
diff --git a/contrib/opie/permsfile.c b/contrib/opie/permsfile.c
new file mode 100644
index 0000000..10b98c5
--- /dev/null
+++ b/contrib/opie/permsfile.c
@@ -0,0 +1,163 @@
+/* permsfile.c: implement SunOS /etc/fbtab and Solaris /etc/logindevperm
+ functionality to set device permissions on login
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.3. Check for NULL return from
+ ftpglob(), combine some expressions, fix a typo. Made file
+ selection a bit more generic.
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Add opie.h. Ifdef around a header.
+ Written at NRL for OPIE 2.0.
+*/
+
+#include "opie_cfg.h"
+#ifdef HAVE_LOGIN_PERMFILE
+#include <stdio.h>
+#include <sys/types.h>
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <syslog.h>
+#include "opie.h"
+
+/* Line buffer size (one more than max line length) */
+#define BUFSIZE 128
+/* Maximum number of list items in a field */
+#define LISTSIZE 10
+
+static char buf[BUFSIZE], buf2[8];
+
+char **ftpglob __P((char *));
+
+VOIDRET opiefatal FUNCTION((x), char *x)
+{
+ fprintf(stderr, x);
+ exit(1);
+}
+
+#include "glob.c"
+
+static int getalist FUNCTION((string, list), char **string AND char **list)
+{
+ char *s = *string;
+ int i = 0;
+
+ while (*s && (*s != '\n') && (*s != ' ') && (*s != '\t'))
+ if ((*s == ':') || (*s == ',')) {
+ *(s++) = 0;
+ list[i++] = *string;
+ *string = s;
+ if (i == LISTSIZE)
+ return i;
+ } else
+ s++;
+
+ if ((int) (s) - (int) (*string)) {
+ *s = 0;
+ list[i++] = *string;
+ }
+ *string = ++s;
+
+ return i;
+}
+
+static VOIDRET doaline FUNCTION((line, name, ttyn, uid, gid), char *line AND char *name AND char *ttyn AND uid_t uid AND gid_t gid)
+{
+ char *ptr;
+ int i;
+ int applies, llen;
+ char *listbuf[LISTSIZE], **globlist;
+
+ if (ptr = strchr(buf, '#'))
+ *ptr = 0;
+
+ /* Skip whitespace */
+ for (ptr = buf; *ptr && ((*ptr == ' ') || (*ptr == '\t'));
+ ptr++);
+
+ if (!*ptr)
+ return;
+
+ /* (Optional) Field 1: user name(s) */
+ if ((*ptr != '/') && (*ptr != '~')) {
+ llen = getalist(&ptr, listbuf);
+ for (applies = i = 0; (i < llen) && !applies; i++)
+ if (!strcmp(listbuf[i], name))
+ applies++;
+ while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
+ ptr++;
+ if (!applies || !*ptr)
+ return;
+ }
+ /* Field 2: terminal(s) */
+ llen = getalist(&ptr, listbuf);
+ for (applies = i = 0; (i < llen) && !applies; i++)
+ if (!strcmp(listbuf[i], ttyn))
+ applies++;
+
+ while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
+ ptr++;
+
+ if (!applies || !*ptr)
+ return;
+
+ /* Field 3: mode */
+ for (applies = 0; *ptr && (*ptr >= '0') && (*ptr <= '7');
+ applies = (applies << 3) | (*(ptr++) - '0'));
+
+ while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
+ ptr++;
+
+ if (!*ptr)
+ return;
+
+ /* Field 4: devices (the fun part...) */
+ llen = getalist(&ptr, listbuf);
+ for (i = 0; i < llen; i++) {
+ if (globlist = ftpglob(listbuf[i]))
+ while (*globlist) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "setting %s to %d/%d %o", *globlist, uid, gid, applies);
+#endif /* DEBUG */
+ if ((chown(*globlist, uid, gid) < 0) && (errno != ENOENT))
+ perror("chown");
+ if ((chmod(*(globlist++), applies) < 0) && (errno != ENOENT))
+ perror("chmod");
+ }
+ }
+}
+
+VOIDRET permsfile FUNCTION((name, ttyn, uid, gid), char *name AND char *ttyn AND uid_t uid AND gid_t gid)
+{
+ FILE *fh;
+
+ if (!(fh = fopen(HAVE_LOGIN_PERMFILE, "r"))) {
+ syslog(LOG_ERR, "Can't open %s!", HAVE_LOGIN_PERMFILE);
+ fprintf(stderr, "Warning: Can't set device permissions.\n");
+ return;
+ }
+ do {
+ if (feof(fh))
+ return;
+ if (fgets(buf, BUFSIZE, fh) == NULL)
+ return;
+ buf[BUFSIZE] = 0;
+
+ doaline(buf, name, ttyn, uid, gid);
+ }
+ while (1);
+}
+#endif /* HAVE_LOGIN_PERMFILE */
diff --git a/contrib/opie/popen.c b/contrib/opie/popen.c
new file mode 100644
index 0000000..22477a6
--- /dev/null
+++ b/contrib/opie/popen.c
@@ -0,0 +1,204 @@
+/* popen.c: A "safe" pipe open routine.
+
+%%% portions-copyright-cmetz
+Portions of this software are Copyright 1996 by Craig Metz, All Rights
+Reserved. The Inner Net License Version 2 applies to these portions of
+the software.
+You should have received a copy of the license with this software. If
+you didn't get a copy, you may request one from <license@inner.net>.
+
+Portions of this software are Copyright 1995 by Randall Atkinson and Dan
+McDonald, All Rights Reserved. All Rights under this copyright are assigned
+to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
+License Agreement applies to this software.
+
+ History:
+
+ Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
+ Removed useless string. ifdef around some headers.
+ Modified at NRL for OPIE 2.1. Optimized for only one pipe at a time.
+ Added minimal version of sigprocmask(). Moved some pid_t
+ dancing to the config headers.
+ Modified at NRL for OPIE 2.0.
+ Originally from BSD.
+
+*/
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 "opie_cfg.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+#if HAVE_SYS_SIGNAL_H
+#include <sys/signal.h>
+#endif /* HAVE_SYS_SIGNAL_H */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <stdio.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+
+#include "opie.h"
+
+char **ftpglob __P((register char *));
+char **copyblk __P((char **));
+VOIDRET blkfree __P((char **));
+
+/*
+ * Special version of popen which avoids call to shell. This insures noone
+ * may create a pipe to a hidden program as a side effect of a list or dir
+ * command.
+ */
+static pid_t child_pid = -1;
+static int pipe_fd;
+
+FILE *ftpd_popen FUNCTION((program, type), char *program AND char *type)
+{
+ register char *cp;
+ FILE *iop;
+ int argc, gargc, pdes[2];
+ char **pop, *argv[100], *gargv[1000], *vv[2];
+
+ if ((*type != 'r' && *type != 'w') || type[1])
+ return (NULL);
+
+ if (pipe(pdes) < 0)
+ return (NULL);
+
+ /* break up string into pieces */
+ for (argc = 0, cp = program;; cp = NULL)
+ if (!(argv[argc++] = strtok(cp, " \t\n")))
+ break;
+
+ /* glob each piece */
+ gargv[0] = argv[0];
+ for (gargc = argc = 1; argv[argc]; argc++) {
+ if (!(pop = (char **) ftpglob(argv[argc]))) {
+ /* globbing failed */
+ vv[0] = argv[argc];
+ vv[1] = NULL;
+ pop = (char **) copyblk(vv);
+ }
+ argv[argc] = (char *) pop; /* save to free later */
+ while (*pop && gargc < 1000)
+ gargv[gargc++] = *pop++;
+ }
+ gargv[gargc] = NULL;
+
+ iop = NULL;
+ switch (child_pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ goto pfree;
+ /* NOTREACHED */
+ case 0: /* child */
+ if (*type == 'r') {
+ if (pdes[1] != 1) {
+ dup2(pdes[1], 1);
+ dup2(pdes[1], 2); /* stderr, too! */
+ close(pdes[1]);
+ }
+ close(pdes[0]);
+ } else {
+ if (pdes[0] != 0) {
+ dup2(pdes[0], 0);
+ close(pdes[0]);
+ }
+ close(pdes[1]);
+ }
+ execv(gargv[0], gargv);
+ _exit(1);
+ }
+
+ /* parent; assume fdopen can't fail... */
+ if (*type == 'r') {
+ iop = fdopen(pipe_fd = pdes[0], type);
+ close(pdes[1]);
+ } else {
+ iop = fdopen(pipe_fd = pdes[1], type);
+ close(pdes[0]);
+ }
+
+pfree: for (argc = 1; argv[argc] != NULL; argc++) {
+ blkfree((char **) argv[argc]);
+ free((char *) argv[argc]);
+ }
+ return (iop);
+}
+
+int ftpd_pclose FUNCTION((iop), FILE *iop)
+{
+ int status;
+ pid_t pid;
+ sigset_t omask, mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGHUP);
+
+ /* pclose returns -1 if stream is not associated with a `popened' command,
+ or, if already `pclosed'. */
+ if ((child_pid < 0) || (fileno(iop) != pipe_fd))
+ return (-1);
+
+ fclose(iop);
+ sigprocmask(SIG_BLOCK, &mask, &omask);
+
+ while ((pid = wait(&status)) != child_pid && (pid != -1));
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ child_pid = -1;
+ pipe_fd = -1;
+
+#ifdef WEXITSTATUS
+ /* this is the fully POSIX compliant implementation */
+ return (pid == -1 ? -1 : WEXITSTATUS(status));
+#else
+ return (pid == -1 ? -1 : status.w_status);
+#endif
+}
OpenPOWER on IntegriCloud