changeset 288:c02c4eb95f95 noffle

[svn] * src/configfile.h,src/configfile.c,docs/noffle.conf.5: Add noffle-user and noffle-group configs. * src/configfile.c,src/fetch.c,src/fetchlist.c,src/protocol.c, src/server.c: Replace strcpy() with Utl_cpyStr() where appropriate. See Debian bug 168128. * src/control.c,src/configfile.c,src/noffle.c: Replace [s]scanf("%s") with [s]scanf(MAXCHAR_FMT). * src/noffle.c: Log warning if noffle.conf is world readable. * src/noffle.c: Restrict most options to news admins; i.e. those who are root or news on running Noffle. * Makefile.in,acconfig.h,aclocal.m4,config.h.in,configure,configure.in, docs/Makefile.in,docs/noffle.conf.5,packages/Makefile.in, packages/redhat/Makefile.in,src/Makefile.am,src/Makefile.in, src/authenticate.c,src/authenticate.h,src/noffle.c,src/server.c: Add basic authentication using either Noffle-specific user file or authenticating via PAM (service 'noffle'). PAM authentication needs to run as root, so a Noffle server that needs PAM must be started by root. Helpful (?) error messages will be logged if not. Noffle will switch ruid and euid to 'news' (or whatever is configured) ASAP. * src/noffle.c: Add uid checking.
author bears
date Fri, 10 Jan 2003 23:25:45 +0000
parents 01755687c565
children 0eaad46e56e2
files ChangeLog Makefile.in acconfig.h aclocal.m4 config.h.in configure configure.in docs/Makefile.in docs/noffle.conf.5 packages/Makefile.in packages/redhat/Makefile.in src/Makefile.am src/Makefile.in src/authenticate.c src/authenticate.h src/noffle.c src/server.c
diffstat 17 files changed, 1299 insertions(+), 238 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Jan 10 23:11:43 2003 +0000
+++ b/ChangeLog	Fri Jan 10 23:25:45 2003 +0000
@@ -1,3 +1,37 @@
+Fri Jan 10 2003 Jim Hague <jim.hague@acm.org>
+
+* docs/noffle.1: Correct Noffle home page location and add Mirko as author.
+  Also update Markus's email. Debian bug 173743.
+* AUTHORS. Great maintainer I am, can't even credit myself.
+* src/fetch.c: Add Reply-To to the front of the list of headers searched
+  for the article author's email when sending posting SNAFU message.
+  Debian bug 156952.
+* src/configfile.h,src/configfile.c,docs/noffle.conf.5: Add noffle-user
+  and noffle-group configs.
+* src/configfile.c,src/fetch.c,src/fetchlist.c,src/protocol.c,
+  src/server.c: Replace strcpy() with Utl_cpyStr() where appropriate.
+  See Debian bug 168128.
+* src/client.c. Replace strcpy() here too.
+* src/control.c,src/configfile.c,src/noffle.c: Replace [s]scanf("%s")
+  with [s]scanf(MAXCHAR_FMT).
+* Makefile.am: Install executable owner news.news mode 06755. Install
+  sample noffle.conf as 0640 news.news.
+* src/noffle.c: Log warning if noffle.conf is world readable.
+* src/noffle.c: Restrict most options to news admins; i.e. those who
+  are root or news on running Noffle.
+* src/configfile.c: Change snprintf() to Utl_cpyStr();
+* Makefile.in,acconfig.h,aclocal.m4,config.h.in,configure,configure.in,
+  docs/Makefile.in,docs/noffle.conf.5,packages/Makefile.in,
+  packages/redhat/Makefile.in,src/Makefile.am,src/Makefile.in,
+  src/authenticate.c,src/authenticate.h,src/noffle.c,src/server.c:
+  Add basic authentication using either Noffle-specific user file
+  or authenticating via PAM (service 'noffle'). PAM authentication
+  needs to run as root, so a Noffle server that needs PAM
+  must be started by root. Helpful (?) error messages will be logged
+  if not. Noffle will switch ruid and euid to 'news' (or whatever
+  is configured) ASAP.
+* src/noffle.c: Add uid checking.
+ 
 Mon Jan 6 2003 Jim Hague <jim.hague@acm.org>
 
 * src/database.c,src/post.c,src/protocol.h,src/protocol.c: When posting,
--- a/Makefile.in	Fri Jan 10 23:11:43 2003 +0000
+++ b/Makefile.in	Fri Jan 10 23:25:45 2003 +0000
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -62,10 +62,12 @@
 CC = @CC@
 CONFIGFILE = @CONFIGFILE@
 DOCDIR = @DOCDIR@
+LIBPAM = @LIBPAM@
 MAKEINFO = @MAKEINFO@
 PACKAGE = @PACKAGE@
 SENDMAILPROG = @SENDMAILPROG@
 SPOOLDIR = @SPOOLDIR@
+USERSFILE = @USERSFILE@
 VERSION = @VERSION@
 
 SUBDIRS = src docs packages
@@ -96,7 +98,7 @@
 $(ACLOCAL_M4):  configure.in 
 	cd $(srcdir) && $(ACLOCAL)
 
-config.status: $(srcdir)/configure.in $(CONFIG_STATUS_DEPENDENCIES)
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
 	$(SHELL) ./config.status --recheck
 $(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
 	cd $(srcdir) && $(AUTOCONF)
@@ -165,7 +167,7 @@
 	dot_seen=no; \
 	rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
 	  rev="$$subdir $$rev"; \
-	  test "$$subdir" = "." && dot_seen=yes; \
+	  test "$$subdir" != "." || dot_seen=yes; \
 	done; \
 	test "$$dot_seen" = "no" && rev=". $$rev"; \
 	target=`echo $@ | sed s/-recursive//`; \
@@ -207,7 +209,7 @@
 	  awk '    { files[$$0] = 1; } \
 	       END { for (i in files) print i; }'`; \
 	test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
+	  || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP))
 
 mostlyclean-tags:
 
@@ -357,14 +359,14 @@
 
 
 install-data-local:
-	$(INSTALL) -m 2755 -o news -g news -d $(DESTDIR)$(SPOOLDIR)
+	$(INSTALL) -m 06755 -o news -g news -d $(DESTDIR)$(SPOOLDIR)
 	$(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/data
 	$(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/lock
 	$(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/requested
 	$(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/outgoing
 	$(INSTALL) -o news -g news -d $(DESTDIR)$(SPOOLDIR)/overview
 	chown -R news.news $(DESTDIR)$(SPOOLDIR)
-	$(INSTALL) -m 755 -o 0 -g 0 -d $(DESTDIR)$(DOCDIR)
+	$(INSTALL) -m 0755 -o 0 -g 0 -d $(DESTDIR)$(DOCDIR)
 	$(INSTALL_DATA) -o 0 -g 0 $(srcdir)/AUTHORS $(DESTDIR)$(DOCDIR)
 	$(INSTALL_DATA) -o 0 -g 0 $(srcdir)/COPYING $(DESTDIR)$(DOCDIR)
 	$(INSTALL_DATA) -o 0 -g 0 $(srcdir)/ChangeLog $(DESTDIR)$(DOCDIR)
@@ -375,7 +377,7 @@
 	$(INSTALL_DATA) -D -o 0 -g 0 $(srcdir)/noffle.conf.example \
                                   $(DESTDIR)$(CONFIGFILE).example
 	chown news.news $(DESTDIR)$(CONFIGFILE).example
-	chmod 600 $(DESTDIR)$(CONFIGFILE).example
+	chmod 0640 $(DESTDIR)$(CONFIGFILE).example
 	@echo
 	@echo "****************************************************************"
 	@echo "You should now copy $(DESTDIR)$(CONFIGFILE).example to $(CONFIGFILE)"
@@ -385,7 +387,7 @@
 
 install-exec-local:
 	chown news.news $(DESTDIR)$(bindir)/`echo $(PACKAGE)|sed '$(transform)'`
-	chmod 4755 $(DESTDIR)$(bindir)/`echo $(PACKAGE)|sed '$(transform)'`
+	chmod 06755 $(DESTDIR)$(bindir)/`echo $(PACKAGE)|sed '$(transform)'`
 
 uninstall-local:
 	rm -f $(DESTDIR)$(DOCDIR)/AUTHORS
--- a/acconfig.h	Fri Jan 10 23:11:43 2003 +0000
+++ b/acconfig.h	Fri Jan 10 23:25:45 2003 +0000
@@ -6,6 +6,9 @@
 /* The NOFFLE config-file */
 #undef CONFIGFILE
 
+/* The NOFFLE users-file */
+#undef USERSFILE
+
 /* The default NOFFLE spool-directory */
 #undef SPOOLDIR
 
@@ -18,6 +21,12 @@
 /* path to sendmail binary */
 #undef SENDMAILPROG
 
+/* Is authentication enabled? */
+#undef USE_AUTH
+
+/* Are we using PAM for authentication? */
+#undef USE_PAM
+
 @TOP@
 /* autoheader generated things inserted here. */
 @BOTTOM@
--- a/aclocal.m4	Fri Jan 10 23:11:43 2003 +0000
+++ b/aclocal.m4	Fri Jan 10 23:25:45 2003 +0000
@@ -1,6 +1,6 @@
-dnl aclocal.m4 generated automatically by aclocal 1.4-p4
+dnl aclocal.m4 generated automatically by aclocal 1.4-p6
 
-dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -12,7 +12,7 @@
 
 # Like AC_CONFIG_HEADER, but automatically create stamp file.
 
-AC_DEFUN(AM_CONFIG_HEADER,
+AC_DEFUN([AM_CONFIG_HEADER],
 [AC_PREREQ([2.12])
 AC_CONFIG_HEADER([$1])
 dnl When config.status generates a header, we must update the stamp-h file.
@@ -42,8 +42,9 @@
 dnl Usage:
 dnl AM_INIT_AUTOMAKE(package,version, [no-define])
 
-AC_DEFUN(AM_INIT_AUTOMAKE,
-[AC_REQUIRE([AC_PROG_INSTALL])
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])
 PACKAGE=[$1]
 AC_SUBST(PACKAGE)
 VERSION=[$2]
@@ -59,18 +60,47 @@
 AC_REQUIRE([AC_ARG_PROGRAM])
 dnl FIXME This is truly gross.
 missing_dir=`cd $ac_aux_dir && pwd`
-AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir)
 AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
-AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir)
 AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
 AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
 AC_REQUIRE([AC_PROG_MAKE_SET])])
 
+# Copyright 2002  Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+	 [AM_AUTOMAKE_VERSION([1.4-p6])])
+
 #
 # Check to make sure that the build environment is sane.
 #
 
-AC_DEFUN(AM_SANITY_CHECK,
+AC_DEFUN([AM_SANITY_CHECK],
 [AC_MSG_CHECKING([whether build environment is sane])
 # Just in case
 sleep 1
@@ -111,7 +141,7 @@
 
 dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
 dnl The program must properly implement --version.
-AC_DEFUN(AM_MISSING_PROG,
+AC_DEFUN([AM_MISSING_PROG],
 [AC_MSG_CHECKING(for working $2)
 # Run test in a subshell; some versions of sh will print an error if
 # an executable is not found, even if stderr is redirected.
@@ -125,3 +155,30 @@
 fi
 AC_SUBST($1)])
 
+# isc-posix.m4 serial 2 (gettext-0.11.2)
+dnl Copyright (C) 1995-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# This file is not needed with autoconf-2.53 and newer.  Remove it in 2005.
+
+# This test replaces the one in autoconf.
+# Currently this macro should have the same name as the autoconf macro
+# because gettext's gettext.m4 (distributed in the automake package)
+# still uses it.  Otherwise, the use in gettext.m4 makes autoheader
+# give these diagnostics:
+#   configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX
+#   configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX
+
+undefine([AC_ISC_POSIX])
+
+AC_DEFUN([AC_ISC_POSIX],
+  [
+    dnl This test replaces the obsolescent AC_ISC_POSIX kludge.
+    AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"])
+  ]
+)
+
--- a/config.h.in	Fri Jan 10 23:11:43 2003 +0000
+++ b/config.h.in	Fri Jan 10 23:25:45 2003 +0000
@@ -7,6 +7,9 @@
 /* The NOFFLE config-file */
 #undef CONFIGFILE
 
+/* The NOFFLE users-file */
+#undef USERSFILE
+
 /* The default NOFFLE spool-directory */
 #undef SPOOLDIR
 
@@ -19,6 +22,12 @@
 /* path to sendmail binary */
 #undef SENDMAILPROG
 
+/* Is authentication enabled? */
+#undef USE_AUTH
+
+/* Are we using PAM for authentication? */
+#undef USE_PAM
+
 
 /* Define if on AIX 3.
    System headers sometimes define this.
@@ -127,6 +136,9 @@
 /* Define if you have the <netdb.h> header file.  */
 #undef HAVE_NETDB_H
 
+/* Define if you have the <pwd.h> header file.  */
+#undef HAVE_PWD_H
+
 /* Define if you have the <regex.h> header file.  */
 #undef HAVE_REGEX_H
 
--- a/configure	Fri Jan 10 23:11:43 2003 +0000
+++ b/configure	Fri Jan 10 23:25:45 2003 +0000
@@ -16,6 +16,10 @@
 ac_help="$ac_help
   --with-gdbm-libdir=DIR  GDBM library files are in DIR"
 ac_help="$ac_help
+  --enable-auth=[no/file/pam] enable authentication [default=no]"
+ac_help="$ac_help
+  --with-usersfile=FILE  users file [/etc/noffle.users]"
+ac_help="$ac_help
   --enable-debug=[no/yes] build with debugging [default=no]"
 ac_help="$ac_help
   --with-docdir=DIR       other documentation [PREFIX/share/doc/noffle]"
@@ -560,6 +564,7 @@
 ac_config_sub=$ac_aux_dir/config.sub
 ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 
+am__api_version="1.4"
 # Find a good install program.  We prefer a C program (faster),
 # so one script is as good as another.  But avoid the broken or
 # incompatible versions:
@@ -572,7 +577,7 @@
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:576: checking for a BSD compatible install" >&5
+echo "configure:581: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -625,7 +630,7 @@
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
 echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
-echo "configure:629: checking whether build environment is sane" >&5
+echo "configure:634: checking whether build environment is sane" >&5
 # Just in case
 sleep 1
 echo timestamp > conftestfile
@@ -682,7 +687,7 @@
 test "$program_transform_name" = "" && program_transform_name="s,x,x,"
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:686: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:691: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -727,21 +732,21 @@
 
 
 missing_dir=`cd $ac_aux_dir && pwd`
-echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
-echo "configure:732: checking for working aclocal" >&5
+echo $ac_n "checking for working aclocal-${am__api_version}""... $ac_c" 1>&6
+echo "configure:737: checking for working aclocal-${am__api_version}" >&5
 # Run test in a subshell; some versions of sh will print an error if
 # an executable is not found, even if stderr is redirected.
 # Redirect stdin to placate older versions of autoconf.  Sigh.
-if (aclocal --version) < /dev/null > /dev/null 2>&1; then
-   ACLOCAL=aclocal
+if (aclocal-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then
+   ACLOCAL=aclocal-${am__api_version}
    echo "$ac_t""found" 1>&6
 else
-   ACLOCAL="$missing_dir/missing aclocal"
+   ACLOCAL="$missing_dir/missing aclocal-${am__api_version}"
    echo "$ac_t""missing" 1>&6
 fi
 
 echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
-echo "configure:745: checking for working autoconf" >&5
+echo "configure:750: checking for working autoconf" >&5
 # Run test in a subshell; some versions of sh will print an error if
 # an executable is not found, even if stderr is redirected.
 # Redirect stdin to placate older versions of autoconf.  Sigh.
@@ -753,21 +758,21 @@
    echo "$ac_t""missing" 1>&6
 fi
 
-echo $ac_n "checking for working automake""... $ac_c" 1>&6
-echo "configure:758: checking for working automake" >&5
+echo $ac_n "checking for working automake-${am__api_version}""... $ac_c" 1>&6
+echo "configure:763: checking for working automake-${am__api_version}" >&5
 # Run test in a subshell; some versions of sh will print an error if
 # an executable is not found, even if stderr is redirected.
 # Redirect stdin to placate older versions of autoconf.  Sigh.
-if (automake --version) < /dev/null > /dev/null 2>&1; then
-   AUTOMAKE=automake
+if (automake-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake-${am__api_version}
    echo "$ac_t""found" 1>&6
 else
-   AUTOMAKE="$missing_dir/missing automake"
+   AUTOMAKE="$missing_dir/missing automake-${am__api_version}"
    echo "$ac_t""missing" 1>&6
 fi
 
 echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
-echo "configure:771: checking for working autoheader" >&5
+echo "configure:776: checking for working autoheader" >&5
 # Run test in a subshell; some versions of sh will print an error if
 # an executable is not found, even if stderr is redirected.
 # Redirect stdin to placate older versions of autoconf.  Sigh.
@@ -780,7 +785,7 @@
 fi
 
 echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
-echo "configure:784: checking for working makeinfo" >&5
+echo "configure:789: checking for working makeinfo" >&5
 # Run test in a subshell; some versions of sh will print an error if
 # an executable is not found, even if stderr is redirected.
 # Redirect stdin to placate older versions of autoconf.  Sigh.
@@ -813,7 +818,7 @@
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:817: checking for $ac_word" >&5
+echo "configure:822: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -843,7 +848,7 @@
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:847: checking for $ac_word" >&5
+echo "configure:852: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -894,7 +899,7 @@
       # Extract the first word of "cl", so it can be a program name with args.
 set dummy cl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:898: checking for $ac_word" >&5
+echo "configure:903: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -926,7 +931,7 @@
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:930: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:935: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -937,12 +942,12 @@
 
 cat > conftest.$ac_ext << EOF
 
-#line 941 "configure"
+#line 946 "configure"
 #include "confdefs.h"
 
 main(){return(0);}
 EOF
-if { (eval echo configure:946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -968,12 +973,12 @@
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:972: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:977: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:977: checking whether we are using GNU C" >&5
+echo "configure:982: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -982,7 +987,7 @@
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:986: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:991: \"$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
@@ -1001,7 +1006,7 @@
 ac_save_CFLAGS="$CFLAGS"
 CFLAGS=
 echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1005: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:1010: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1033,7 +1038,7 @@
 fi
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1037: checking how to run the C preprocessor" >&5
+echo "configure:1042: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -1048,13 +1053,13 @@
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 1052 "configure"
+#line 1057 "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:1058: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1063: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1065,13 +1070,13 @@
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 1069 "configure"
+#line 1074 "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:1075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1080: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1082,13 +1087,13 @@
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 1086 "configure"
+#line 1091 "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:1092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1097: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1114,13 +1119,13 @@
 
 if test $ac_cv_prog_gcc = yes; then
     echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:1118: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:1123: checking whether ${CC-cc} needs -traditional" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
     ac_pattern="Autoconf.*'x'"
   cat > conftest.$ac_ext <<EOF
-#line 1124 "configure"
+#line 1129 "configure"
 #include "confdefs.h"
 #include <sgtty.h>
 Autoconf TIOCGETP
@@ -1138,7 +1143,7 @@
 
   if test $ac_cv_prog_gcc_traditional = no; then
     cat > conftest.$ac_ext <<EOF
-#line 1142 "configure"
+#line 1147 "configure"
 #include "confdefs.h"
 #include <termio.h>
 Autoconf TCGETA
@@ -1171,7 +1176,7 @@
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1175: checking for a BSD compatible install" >&5
+echo "configure:1180: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1224,7 +1229,7 @@
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:1228: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:1233: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1254,7 +1259,7 @@
 # Extract the first word of "sendmail", so it can be a program name with args.
 set dummy sendmail; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1258: checking for $ac_word" >&5
+echo "configure:1263: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_SENDMAILPROG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1293,9 +1298,9 @@
 
 
 echo $ac_n "checking for AIX""... $ac_c" 1>&6
-echo "configure:1297: checking for AIX" >&5
+echo "configure:1302: checking for AIX" >&5
 cat > conftest.$ac_ext <<EOF
-#line 1299 "configure"
+#line 1304 "configure"
 #include "confdefs.h"
 #ifdef _AIX
   yes
@@ -1316,40 +1321,62 @@
 rm -f conftest*
 
 
-echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
-echo "configure:1321: checking for POSIXized ISC" >&5
-if test -d /etc/conf/kconfig.d &&
-  grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
-then
+
+        echo $ac_n "checking for strerror in -lcposix""... $ac_c" 1>&6
+echo "configure:1327: checking for strerror in -lcposix" >&5
+ac_lib_var=`echo cposix'_'strerror | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lcposix  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1335 "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 strerror();
+
+int main() {
+strerror()
+; return 0; }
+EOF
+if { (eval echo configure:1346: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-  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
+  LIBS="$LIBS -lcposix"
 else
   echo "$ac_t""no" 1>&6
-  ISC=
 fi
 
+  
+
 ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
-echo "configure:1343: checking for minix/config.h" >&5
+echo "configure:1370: checking for minix/config.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1348 "configure"
+#line 1375 "configure"
 #include "confdefs.h"
 #include <minix/config.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1353: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1380: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1398,12 +1425,12 @@
 # [ This is ripped from GNU tar. ]
 
 echo $ac_n "checking for gethostent""... $ac_c" 1>&6
-echo "configure:1402: checking for gethostent" >&5
+echo "configure:1429: checking for gethostent" >&5
 if eval "test \"`echo '$''{'ac_cv_func_gethostent'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1407 "configure"
+#line 1434 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char gethostent(); below.  */
@@ -1426,7 +1453,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1430: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_gethostent=yes"
 else
@@ -1447,7 +1474,7 @@
 
 if test $ac_cv_func_gethostent = no; then
   echo $ac_n "checking for gethostent in -lnsl""... $ac_c" 1>&6
-echo "configure:1451: checking for gethostent in -lnsl" >&5
+echo "configure:1478: checking for gethostent in -lnsl" >&5
 ac_lib_var=`echo nsl'_'gethostent | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1455,7 +1482,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1459 "configure"
+#line 1486 "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
@@ -1466,7 +1493,7 @@
 gethostent()
 ; return 0; }
 EOF
-if { (eval echo configure:1470: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1495,12 +1522,12 @@
 
 fi
 echo $ac_n "checking for setsockopt""... $ac_c" 1>&6
-echo "configure:1499: checking for setsockopt" >&5
+echo "configure:1526: checking for setsockopt" >&5
 if eval "test \"`echo '$''{'ac_cv_func_setsockopt'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1504 "configure"
+#line 1531 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char setsockopt(); below.  */
@@ -1523,7 +1550,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_setsockopt=yes"
 else
@@ -1544,7 +1571,7 @@
 
 if test $ac_cv_func_setsockopt = no; then
   echo $ac_n "checking for setsockopt in -lsocket""... $ac_c" 1>&6
-echo "configure:1548: checking for setsockopt in -lsocket" >&5
+echo "configure:1575: checking for setsockopt in -lsocket" >&5
 ac_lib_var=`echo socket'_'setsockopt | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1552,7 +1579,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1556 "configure"
+#line 1583 "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
@@ -1563,7 +1590,7 @@
 setsockopt()
 ; return 0; }
 EOF
-if { (eval echo configure:1567: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1594: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1607,7 +1634,7 @@
 fi
 
 echo $ac_n "checking for gdbm_open in -lgdbm""... $ac_c" 1>&6
-echo "configure:1611: checking for gdbm_open in -lgdbm" >&5
+echo "configure:1638: checking for gdbm_open in -lgdbm" >&5
 ac_lib_var=`echo gdbm'_'gdbm_open | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1615,7 +1642,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lgdbm  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1619 "configure"
+#line 1646 "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
@@ -1626,7 +1653,7 @@
 gdbm_open()
 ; return 0; }
 EOF
-if { (eval echo configure:1630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1657: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1643,17 +1670,17 @@
   echo "$ac_t""yes" 1>&6
   ac_safe=`echo "gdbm.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for gdbm.h""... $ac_c" 1>&6
-echo "configure:1647: checking for gdbm.h" >&5
+echo "configure:1674: checking for gdbm.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1652 "configure"
+#line 1679 "configure"
 #include "confdefs.h"
 #include <gdbm.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1657: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1683,12 +1710,12 @@
 
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1687: checking for ANSI C header files" >&5
+echo "configure:1714: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1692 "configure"
+#line 1719 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -1696,7 +1723,7 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1727: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1713,7 +1740,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1717 "configure"
+#line 1744 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1731,7 +1758,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1735 "configure"
+#line 1762 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1752,7 +1779,7 @@
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 1756 "configure"
+#line 1783 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1763,7 +1790,7 @@
 exit (0); }
 
 EOF
-if { (eval echo configure:1767: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -1791,12 +1818,12 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1795: checking for $ac_hdr that defines DIR" >&5
+echo "configure:1822: checking for $ac_hdr that defines DIR" >&5
 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1800 "configure"
+#line 1827 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <$ac_hdr>
@@ -1804,7 +1831,7 @@
 DIR *dirp = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:1808: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1835: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_header_dirent_$ac_safe=yes"
 else
@@ -1829,7 +1856,7 @@
 # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
 if test $ac_header_dirent = dirent.h; then
 echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1833: checking for opendir in -ldir" >&5
+echo "configure:1860: checking for opendir in -ldir" >&5
 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1837,7 +1864,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldir  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1841 "configure"
+#line 1868 "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
@@ -1848,7 +1875,7 @@
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:1852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1870,7 +1897,7 @@
 
 else
 echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1874: checking for opendir in -lx" >&5
+echo "configure:1901: checking for opendir in -lx" >&5
 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1878,7 +1905,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lx  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1882 "configure"
+#line 1909 "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
@@ -1889,7 +1916,7 @@
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:1893: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1915,17 +1942,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1919: checking for $ac_hdr" >&5
+echo "configure:1946: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1924 "configure"
+#line 1951 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1929: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1956: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1955,17 +1982,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1959: checking for $ac_hdr" >&5
+echo "configure:1986: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1964 "configure"
+#line 1991 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1969: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1996: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1995,17 +2022,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1999: checking for $ac_hdr" >&5
+echo "configure:2026: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2004 "configure"
+#line 2031 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2009: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2031,21 +2058,21 @@
 fi
 done
 
-for ac_hdr in sys/types.h regex.h
+for ac_hdr in sys/types.h regex.h pwd.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2039: checking for $ac_hdr" >&5
+echo "configure:2066: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2044 "configure"
+#line 2071 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2049: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2076: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2075,12 +2102,12 @@
 
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:2079: checking for working const" >&5
+echo "configure:2106: checking for working const" >&5
 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 2084 "configure"
+#line 2111 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -2129,7 +2156,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2133: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2160: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -2150,12 +2177,12 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:2154: checking for size_t" >&5
+echo "configure:2181: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2159 "configure"
+#line 2186 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -2183,12 +2210,12 @@
 fi
 
 echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:2187: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:2214: checking whether time.h and sys/time.h may both be included" >&5
 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2192 "configure"
+#line 2219 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/time.h>
@@ -2197,7 +2224,7 @@
 struct tm *tp;
 ; return 0; }
 EOF
-if { (eval echo configure:2201: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2228: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_time=yes
 else
@@ -2218,12 +2245,12 @@
 fi
 
 echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:2222: checking whether struct tm is in sys/time.h or time.h" >&5
+echo "configure:2249: checking whether struct tm is in sys/time.h or time.h" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2227 "configure"
+#line 2254 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <time.h>
@@ -2231,7 +2258,7 @@
 struct tm *tp; tp->tm_sec;
 ; return 0; }
 EOF
-if { (eval echo configure:2235: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2262: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_tm=time.h
 else
@@ -2253,12 +2280,12 @@
 
 
 echo $ac_n "checking socklen_t""... $ac_c" 1>&6
-echo "configure:2257: checking socklen_t" >&5
+echo "configure:2284: checking socklen_t" >&5
 if eval "test \"`echo '$''{'noffle_cv_type_socklen_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2262 "configure"
+#line 2289 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -2268,7 +2295,7 @@
  socklen_t s; 
 ; return 0; }
 EOF
-if { (eval echo configure:2272: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2299: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   noffle_cv_type_socklen_t=yes
 else
@@ -2294,12 +2321,12 @@
 
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:2298: checking return type of signal handlers" >&5
+echo "configure:2325: checking return type of signal handlers" >&5
 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 2303 "configure"
+#line 2330 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -2316,7 +2343,7 @@
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:2320: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2347: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
@@ -2335,12 +2362,12 @@
 
 
 echo $ac_n "checking for strftime""... $ac_c" 1>&6
-echo "configure:2339: checking for strftime" >&5
+echo "configure:2366: checking for strftime" >&5
 if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2344 "configure"
+#line 2371 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char strftime(); below.  */
@@ -2363,7 +2390,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2367: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_strftime=yes"
 else
@@ -2385,7 +2412,7 @@
   echo "$ac_t""no" 1>&6
 # strftime is in -lintl on SCO UNIX.
 echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6
-echo "configure:2389: checking for strftime in -lintl" >&5
+echo "configure:2416: checking for strftime in -lintl" >&5
 ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -2393,7 +2420,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lintl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2397 "configure"
+#line 2424 "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
@@ -2404,7 +2431,7 @@
 strftime()
 ; return 0; }
 EOF
-if { (eval echo configure:2408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2435: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -2431,7 +2458,7 @@
 fi
 
 echo $ac_n "checking for working fnmatch""... $ac_c" 1>&6
-echo "configure:2435: checking for working fnmatch" >&5
+echo "configure:2462: checking for working fnmatch" >&5
 if eval "test \"`echo '$''{'ac_cv_func_fnmatch_works'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2442,11 +2469,11 @@
   ac_cv_func_fnmatch_works=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 2446 "configure"
+#line 2473 "configure"
 #include "confdefs.h"
 main() { exit (fnmatch ("a*", "abc", 0) != 0); }
 EOF
-if { (eval echo configure:2450: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2477: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_func_fnmatch_works=yes
 else
@@ -2471,12 +2498,12 @@
 for ac_func in fdopen mkdir select socket
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2475: checking for $ac_func" >&5
+echo "configure:2502: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2480 "configure"
+#line 2507 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2499,7 +2526,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2503: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2530: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2526,12 +2553,12 @@
 for ac_func in gethostname uname
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2530: checking for $ac_func" >&5
+echo "configure:2557: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2535 "configure"
+#line 2562 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2554,7 +2581,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2558: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2585: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2581,12 +2608,12 @@
 for ac_func in snprintf vsnprintf __vsnprintf __snprintf
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2585: checking for $ac_func" >&5
+echo "configure:2612: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2590 "configure"
+#line 2617 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2609,7 +2636,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2613: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2640: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2636,12 +2663,12 @@
 for ac_func in strerror strstr
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2640: checking for $ac_func" >&5
+echo "configure:2667: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2645 "configure"
+#line 2672 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2664,7 +2691,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2668: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2691,12 +2718,12 @@
 for ac_func in mktime timegm
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2695: checking for $ac_func" >&5
+echo "configure:2722: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2700 "configure"
+#line 2727 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2719,7 +2746,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2723: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2750: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2748,6 +2775,131 @@
 
 
 
+# Check whether --enable-auth or --disable-auth was given.
+if test "${enable_auth+set}" = set; then
+  enableval="$enable_auth"
+  :
+else
+  enable_auth=no
+fi
+
+
+if test "x$enable_auth" = "xfile"; then
+  cat >> confdefs.h <<\EOF
+#define USE_AUTH 1
+EOF
+
+fi
+if test "x$enable_auth" = "xpam"; then
+  
+  echo $ac_n "checking for pam_start in -lpam""... $ac_c" 1>&6
+echo "configure:2797: checking for pam_start in -lpam" >&5
+ac_lib_var=`echo pam'_'pam_start | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lpam  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2805 "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 pam_start();
+
+int main() {
+pam_start()
+; return 0; }
+EOF
+if { (eval echo configure:2816: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  ac_safe=`echo "security/pam_appl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for security/pam_appl.h""... $ac_c" 1>&6
+echo "configure:2833: checking for security/pam_appl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2838 "configure"
+#include "confdefs.h"
+#include <security/pam_appl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+{ echo "configure: error: cannot find security/pam_appl.h" 1>&2; exit 1; }
+fi
+
+else
+  echo "$ac_t""no" 1>&6
+{ echo "configure: error: cannot find libpam" 1>&2; exit 1; }
+fi
+
+  LIBPAM="-lpam"
+  cat >> confdefs.h <<\EOF
+#define USE_PAM 1
+EOF
+
+  cat >> confdefs.h <<\EOF
+#define USE_AUTH 1
+EOF
+
+fi
+
+echo $ac_n "checking usersfile""... $ac_c" 1>&6
+echo "configure:2882: checking usersfile" >&5
+# Check whether --with-usersfile or --without-usersfile was given.
+if test "${with_usersfile+set}" = set; then
+  withval="$with_usersfile"
+  if echo "$withval" | egrep >/dev/null -v '^/' ; then
+    { echo "configure: error: you must give an absolute path" 1>&2; exit 1; }
+  fi
+  withval=`echo "$withval" | sed 'sx/*$xx;'`
+else
+  withval="/etc/$PACKAGE.users"
+
+fi
+
+USERSFILE=$withval
+echo "$ac_t""$USERSFILE" 1>&6
+cat >> confdefs.h <<EOF
+#define USERSFILE "$USERSFILE"
+EOF
+
+
+
+
 # Check whether --enable-debug or --disable-debug was given.
 if test "${enable_debug+set}" = set; then
   enableval="$enable_debug"
@@ -2778,8 +2930,8 @@
   withval="$with_docdir"
   noffle_cv_docdir=$withval
 else
-   echo $ac_n "checking other documentation diretcory""... $ac_c" 1>&6
-echo "configure:2783: checking other documentation diretcory" >&5
+   echo $ac_n "checking other documentation directory""... $ac_c" 1>&6
+echo "configure:2935: checking other documentation directory" >&5
 if eval "test \"`echo '$''{'noffle_cv_docdir'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2798,7 +2950,7 @@
 
 
 echo $ac_n "checking spooldir""... $ac_c" 1>&6
-echo "configure:2802: checking spooldir" >&5
+echo "configure:2954: checking spooldir" >&5
 # Check whether --with-spooldir or --without-spooldir was given.
 if test "${with_spooldir+set}" = set; then
   withval="$with_spooldir"
@@ -2821,7 +2973,7 @@
 
 
 echo $ac_n "checking configfile""... $ac_c" 1>&6
-echo "configure:2825: checking configfile" >&5
+echo "configure:2977: checking configfile" >&5
 # Check whether --with-configfile or --without-configfile was given.
 if test "${with_configfile+set}" = set; then
   withval="$with_configfile"
@@ -3002,6 +3154,8 @@
 s%@CC@%$CC%g
 s%@CPP@%$CPP%g
 s%@SENDMAILPROG@%$SENDMAILPROG%g
+s%@LIBPAM@%$LIBPAM%g
+s%@USERSFILE@%$USERSFILE%g
 s%@SPOOLDIR@%$SPOOLDIR%g
 s%@CONFIGFILE@%$CONFIGFILE%g
 s%@DOCDIR@%$DOCDIR%g
--- a/configure.in	Fri Jan 10 23:11:43 2003 +0000
+++ b/configure.in	Fri Jan 10 23:25:45 2003 +0000
@@ -84,7 +84,7 @@
 AC_CHECK_HEADERS(syslog.h sys/resource.h sys/utsname.h)
 AC_CHECK_HEADERS(fnmatch.h errno.h getopt.h time.h sys/time.h signal.h)
 AC_CHECK_HEADERS(netdb.h sys/socket.h fcntl.h limits.h unistd.h)
-AC_CHECK_HEADERS(sys/types.h regex.h)
+AC_CHECK_HEADERS(sys/types.h regex.h pwd.h)
 
 
 dnl ---------------------------------------------------------------------------
@@ -130,6 +130,43 @@
 
 
 dnl ---------------------------------------------------------------------------
+dnl Authentication options
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_ENABLE(auth,
+[  --enable-auth=[no/file/pam] enable authentication [default=no]], ,
+enable_auth=no)
+
+if test "x$enable_auth" = "xfile"; then
+  AC_DEFINE(USE_AUTH)
+fi
+if test "x$enable_auth" = "xpam"; then
+  AC_SUBST(LIBPAM)
+  AC_CHECK_LIB(pam, pam_start,
+	AC_CHECK_HEADER(security/pam_appl.h,,
+		AC_MSG_ERROR([cannot find security/pam_appl.h])),
+	AC_MSG_ERROR([cannot find libpam]))
+  LIBPAM="-lpam"
+  AC_DEFINE(USE_PAM)
+  AC_DEFINE(USE_AUTH)
+fi
+
+dnl check where to put the users file
+AC_MSG_CHECKING(usersfile)
+AC_ARG_WITH(usersfile,
+  [  --with-usersfile=FILE  users file [/etc/noffle.users]],
+  if echo "$withval" | egrep >/dev/null -v '^/' ; then
+    AC_MSG_ERROR(you must give an absolute path)
+  fi
+  withval=`echo "$withval" | sed 'sx/*$xx;'`,
+  withval="/etc/$PACKAGE.users"
+)
+USERSFILE=$withval
+AC_MSG_RESULT($USERSFILE)
+AC_DEFINE_UNQUOTED(USERSFILE,"$USERSFILE")
+AC_SUBST(USERSFILE)
+
+dnl ---------------------------------------------------------------------------
 dnl Handle user-specified configure options
 dnl ---------------------------------------------------------------------------
 
@@ -156,7 +193,7 @@
 AC_ARG_WITH(docdir,
 [  --with-docdir=DIR       other documentation [PREFIX/share/doc/noffle]],
 [noffle_cv_docdir=$withval],
-[ AC_CACHE_CHECK(other documentation diretcory, noffle_cv_docdir,
+[ AC_CACHE_CHECK(other documentation directory, noffle_cv_docdir,
   [if test x$prefix = xNONE; then
     noffle_cv_prefix=$ac_default_prefix
    else
--- a/docs/Makefile.in	Fri Jan 10 23:11:43 2003 +0000
+++ b/docs/Makefile.in	Fri Jan 10 23:25:45 2003 +0000
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -62,10 +62,12 @@
 CC = @CC@
 CONFIGFILE = @CONFIGFILE@
 DOCDIR = @DOCDIR@
+LIBPAM = @LIBPAM@
 MAKEINFO = @MAKEINFO@
 PACKAGE = @PACKAGE@
 SENDMAILPROG = @SENDMAILPROG@
 SPOOLDIR = @SPOOLDIR@
+USERSFILE = @USERSFILE@
 VERSION = @VERSION@
 
 man_MANS = $(PACKAGE).1 $(PACKAGE).conf.5
--- a/docs/noffle.conf.5	Fri Jan 10 23:11:43 2003 +0000
+++ b/docs/noffle.conf.5	Fri Jan 10 23:25:45 2003 +0000
@@ -1,5 +1,5 @@
 .TH noffle.conf 5
-.\" $Id: noffle.conf.5 381 2002-05-14 14:25:45Z mirkol $
+.\" $Id: noffle.conf.5 420 2003-01-10 23:25:45Z bears $
 
 .SH NAME
 noffle.conf \- Configuration file for NOFFLE news server
@@ -98,6 +98,7 @@
 .BR all ,
 .BR none ,
 .BR config ,
+.BR auth ,
 .BR control ,
 .BR expire ,
 .BR fetch ,
@@ -204,6 +205,22 @@
 Default: yes
 
 .TP
+.B authenticate-client yes|no
+Insist that clients authenticate themselves using the NNTP
+AUTHINFO USER/AUTHINFO PASS transaction before any news is served.
+The form of the authentication is determined at compile time; either
+PAM is used (with a service name "noffle"), or the userlist
+file is scanned. This file, by default \fI/etc/noffle.users\fP,
+is a text file. Spaces, comments starting with '#' and blank lines are
+ignored. Other lines must contain space-separated 'username password'
+pairs. For security reasons the userlist file must be a regular file,
+not a link, and must be owner readable only. Finally, note that the
+NNTP AUTHINFO USER/AUTHINFO PASS transaction is not encrypted in any
+way, and so must itself be considered insecure.
+.br
+Default: no
+
+.TP
 .B post-locally yes|no
 Place articles posted to external servers in the local aticle database
 immediately. Some servers may rewrite Message-IDs, which will cause
@@ -257,6 +274,21 @@
 Default: 14
 
 .TP
+.B noffle-user <n>
+The username under which NOFFLE normally runs. If NOFFLE is invoked by
+root, it will drop its real and effective UID to this user as soon as
+possible.
+.br
+Default: news
+
+.TP
+.B noffle-group <n>
+The group under which NOFFLE normally runs. NOFFLE will change to this
+real and effective GID as soon as possible.
+.br
+Default: news
+
+.TP
 .B expire <group pattern> <n>
 The expiry period for a newsgroup or set of newsgroups, in days. The
 expiry pattern can contain \fIwildcards\fP, and there can be multiple
@@ -287,7 +319,7 @@
 uses a wildcard format that closely matches filename-style wildcards.
 \fIalt.binaries.*\fP, for example, matches all newsgroups under the
 .I alt.binaries
-hierarchy. A full description of the fomat (known as
+hierarchy. A full description of the format (known as
 .B wildmat
 patterns) is as follows.
 
--- a/packages/Makefile.in	Fri Jan 10 23:11:43 2003 +0000
+++ b/packages/Makefile.in	Fri Jan 10 23:25:45 2003 +0000
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -62,10 +62,12 @@
 CC = @CC@
 CONFIGFILE = @CONFIGFILE@
 DOCDIR = @DOCDIR@
+LIBPAM = @LIBPAM@
 MAKEINFO = @MAKEINFO@
 PACKAGE = @PACKAGE@
 SENDMAILPROG = @SENDMAILPROG@
 SPOOLDIR = @SPOOLDIR@
+USERSFILE = @USERSFILE@
 VERSION = @VERSION@
 
 SUBDIRS = redhat
@@ -125,7 +127,7 @@
 	dot_seen=no; \
 	rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
 	  rev="$$subdir $$rev"; \
-	  test "$$subdir" = "." && dot_seen=yes; \
+	  test "$$subdir" != "." || dot_seen=yes; \
 	done; \
 	test "$$dot_seen" = "no" && rev=". $$rev"; \
 	target=`echo $@ | sed s/-recursive//`; \
@@ -167,7 +169,7 @@
 	  awk '    { files[$$0] = 1; } \
 	       END { for (i in files) print i; }'`; \
 	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+	  || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags  $$unique $(LISP))
 
 mostlyclean-tags:
 
--- a/packages/redhat/Makefile.in	Fri Jan 10 23:11:43 2003 +0000
+++ b/packages/redhat/Makefile.in	Fri Jan 10 23:25:45 2003 +0000
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -62,10 +62,12 @@
 CC = @CC@
 CONFIGFILE = @CONFIGFILE@
 DOCDIR = @DOCDIR@
+LIBPAM = @LIBPAM@
 MAKEINFO = @MAKEINFO@
 PACKAGE = @PACKAGE@
 SENDMAILPROG = @SENDMAILPROG@
 SPOOLDIR = @SPOOLDIR@
+USERSFILE = @USERSFILE@
 VERSION = @VERSION@
 
 EXTRA_DIST = noffle-expire noffle.spec
--- a/src/Makefile.am	Fri Jan 10 23:11:43 2003 +0000
+++ b/src/Makefile.am	Fri Jan 10 23:25:45 2003 +0000
@@ -4,6 +4,7 @@
 bin_PROGRAMS = noffle
 
 noffle_SOURCES = \
+authenticate.c authenticate.h \
 client.c client.h \
 common.h \
 configfile.c configfile.h \
@@ -32,7 +33,7 @@
 util.c util.h \
 wildmat.c wildmat.h
 
-noffle_LDADD = -lgdbm
+noffle_LDADD = -lgdbm $(LIBPAM)
 
 tags:
 	etags $(noffle_SOURCES)
--- a/src/Makefile.in	Fri Jan 10 23:11:43 2003 +0000
+++ b/src/Makefile.in	Fri Jan 10 23:25:45 2003 +0000
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -63,18 +63,20 @@
 CC = @CC@
 CONFIGFILE = @CONFIGFILE@
 DOCDIR = @DOCDIR@
+LIBPAM = @LIBPAM@
 MAKEINFO = @MAKEINFO@
 PACKAGE = @PACKAGE@
 SENDMAILPROG = @SENDMAILPROG@
 SPOOLDIR = @SPOOLDIR@
+USERSFILE = @USERSFILE@
 VERSION = @VERSION@
 
 bin_PROGRAMS = noffle
 
-noffle_SOURCES =  client.c client.h common.h configfile.c configfile.h content.c content.h control.c control.h database.c database.h dynamicstring.c dynamicstring.h expire.c expire.h fetch.c fetch.h fetchlist.c fetchlist.h filter.c filter.h group.c group.h itemlist.c itemlist.h lock.c lock.h log.c log.h noffle.c online.c online.h outgoing.c outgoing.h over.c over.h portable.h post.c post.h protocol.c protocol.h pseudo.c pseudo.h request.c request.h server.c server.h util.c util.h wildmat.c wildmat.h
+noffle_SOURCES =  authenticate.c authenticate.h client.c client.h common.h configfile.c configfile.h content.c content.h control.c control.h database.c database.h dynamicstring.c dynamicstring.h expire.c expire.h fetch.c fetch.h fetchlist.c fetchlist.h filter.c filter.h group.c group.h itemlist.c itemlist.h lock.c lock.h log.c log.h noffle.c online.c online.h outgoing.c outgoing.h over.c over.h portable.h post.c post.h protocol.c protocol.h pseudo.c pseudo.h request.c request.h server.c server.h util.c util.h wildmat.c wildmat.h
 
 
-noffle_LDADD = -lgdbm
+noffle_LDADD = -lgdbm $(LIBPAM)
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../config.h
 CONFIG_CLEAN_FILES = 
@@ -85,10 +87,10 @@
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
-noffle_OBJECTS =  client.o configfile.o content.o control.o database.o \
-dynamicstring.o expire.o fetch.o fetchlist.o filter.o group.o \
-itemlist.o lock.o log.o noffle.o online.o outgoing.o over.o post.o \
-protocol.o pseudo.o request.o server.o util.o wildmat.o
+noffle_OBJECTS =  authenticate.o client.o configfile.o content.o \
+control.o database.o dynamicstring.o expire.o fetch.o fetchlist.o \
+filter.o group.o itemlist.o lock.o log.o noffle.o online.o outgoing.o \
+over.o post.o protocol.o pseudo.o request.o server.o util.o wildmat.o
 noffle_DEPENDENCIES = 
 noffle_LDFLAGS = 
 CFLAGS = @CFLAGS@
@@ -102,13 +104,13 @@
 
 TAR = tar
 GZIP_ENV = --best
-DEP_FILES =  .deps/client.P .deps/configfile.P .deps/content.P \
-.deps/control.P .deps/database.P .deps/dynamicstring.P .deps/expire.P \
-.deps/fetch.P .deps/fetchlist.P .deps/filter.P .deps/group.P \
-.deps/itemlist.P .deps/lock.P .deps/log.P .deps/noffle.P .deps/online.P \
-.deps/outgoing.P .deps/over.P .deps/post.P .deps/protocol.P \
-.deps/pseudo.P .deps/request.P .deps/server.P .deps/util.P \
-.deps/wildmat.P
+DEP_FILES =  .deps/authenticate.P .deps/client.P .deps/configfile.P \
+.deps/content.P .deps/control.P .deps/database.P .deps/dynamicstring.P \
+.deps/expire.P .deps/fetch.P .deps/fetchlist.P .deps/filter.P \
+.deps/group.P .deps/itemlist.P .deps/lock.P .deps/log.P .deps/noffle.P \
+.deps/online.P .deps/outgoing.P .deps/over.P .deps/post.P \
+.deps/protocol.P .deps/pseudo.P .deps/request.P .deps/server.P \
+.deps/util.P .deps/wildmat.P
 SOURCES = $(noffle_SOURCES)
 OBJECTS = $(noffle_OBJECTS)
 
@@ -184,7 +186,7 @@
 	  awk '    { files[$$0] = 1; } \
 	       END { for (i in files) print i; }'`; \
 	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+	  || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags  $$unique $(LISP))
 
 mostlyclean-tags:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/authenticate.c	Fri Jan 10 23:25:45 2003 +0000
@@ -0,0 +1,445 @@
+/*
+  authenticate.c
+
+  Do client authentication
+
+  $Id: authenticate.c 420 2003-01-10 23:25:45Z bears $
+*/
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "common.h"
+#include "authenticate.h"
+#include "configfile.h"
+#include "log.h"
+#include "portable.h"
+#include "util.h"
+
+#if USE_AUTH
+
+#if USE_PAM
+#include <security/pam_appl.h>
+
+static const char *password;
+
+/*
+ * It's a bit tricky to go around asking PAM questions at this stage,
+ * as well as not fitting NNTP, so just repond to all PAM questions
+ * with the password and hope that works.
+ */
+static int noffle_conv(	int num_msg, 
+			const struct pam_message **msgm,
+			struct pam_response **response, 
+			void *appdata_ptr	)
+{
+    struct pam_response *reply;
+
+    UNUSED(appdata_ptr);
+    UNUSED(msgm);
+    
+    reply = calloc( num_msg, sizeof (struct pam_response) );
+    reply->resp = strdup( password );
+    reply->resp_retcode = 0;
+    *response = reply;
+    return PAM_SUCCESS;
+}
+
+static struct pam_conv conv = {
+    noffle_conv,
+    NULL
+};
+
+static pam_handle_t *pamh = NULL;
+static Bool pam_session_opened = FALSE;
+static Bool pam_set_cred = FALSE;
+static uid_t oldEuid;
+
+static Bool
+PAM_open( void )
+{
+    int retval;
+
+    /* To use PAM successfully we need to be root. */
+    ASSERT ( getuid() == 0 );
+    
+    ASSERT( pamh == NULL );
+
+    /*
+     * Preserve old eUid to be restored when PAM closes and set
+     * current euid to root for PAMs benefit.
+     */
+    oldEuid = geteuid();
+    if ( seteuid( 0 ) < 0 )
+    {
+	Log_err( "Cannot set euid to root: %s", strerror( errno ) );
+	return FALSE;
+    }
+    
+    retval = pam_start( "noffle", NULL, &conv, &pamh );
+    if ( retval != PAM_SUCCESS )
+    {
+	Log_err( "Cannot starting authentication: %s",
+		 pam_strerror( pamh, retval ) );
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+static enum AuthResult
+PAM_authenticate( const char *user, const char *pass )
+{
+    int retval;
+    
+    ASSERT( pamh != NULL );
+
+    password = pass;
+    
+    retval = pam_set_item( pamh, PAM_USER, user );
+    if ( retval != PAM_SUCCESS )
+	Log_dbg( LOG_DBG_AUTH, "pam_set_item failed: %s",
+		 pam_strerror( pamh, retval ) );
+
+    if ( retval == PAM_SUCCESS )
+    {
+	retval = pam_authenticate( pamh, PAM_SILENT );
+	if ( retval != PAM_SUCCESS )
+	    Log_dbg( LOG_DBG_AUTH, "pam_authenticate failed: %s",
+		     pam_strerror( pamh, retval ) );
+    }
+
+    if ( retval == PAM_SUCCESS )
+    {
+	  retval = pam_setcred( pamh, PAM_ESTABLISH_CRED );
+	  if ( retval != PAM_SUCCESS )
+	      Log_dbg( LOG_DBG_AUTH, "pam_setcred failed: %s",
+		       pam_strerror( pamh, retval ) );
+	  else
+	      pam_set_cred = TRUE;
+    }
+    
+    if ( retval == PAM_SUCCESS )
+    {
+	  retval = pam_open_session( pamh, 0 );
+	  if ( retval != PAM_SUCCESS )
+	      Log_dbg( LOG_DBG_AUTH, "pam_open_session failed: %s",
+		       pam_strerror( pamh, retval ) );
+	  else
+	      pam_session_opened = TRUE;
+    }
+
+    switch ( retval )
+    {
+    case PAM_SUCCESS:
+	return AUTH_OK;
+
+    case PAM_MAXTRIES:
+	return AUTH_DISCONNECT;
+
+    case PAM_ABORT:
+	return AUTH_ERROR;
+    }
+
+    return AUTH_FAILED;
+}
+
+static void
+PAM_close( void )
+{
+    int retval = 0;
+    
+    ASSERT ( pamh != NULL );
+
+    if ( pam_session_opened )
+    {
+	pam_session_opened = FALSE;
+	retval = pam_close_session( pamh, 0 );
+	if ( retval != PAM_SUCCESS )
+	    Log_dbg( LOG_DBG_AUTH, "pam_close_session failed: %s",
+		     pam_strerror( pamh, retval ) );
+    }
+
+    if ( pam_set_cred )
+    {
+	pam_set_cred = FALSE;
+	retval = pam_setcred( pamh, PAM_DELETE_CRED );
+	if ( retval != PAM_SUCCESS )
+	    Log_dbg( LOG_DBG_AUTH, "pam_set_cred failed: %s",
+		     pam_strerror( pamh, retval ) );
+    }
+
+    retval = pam_end( pamh, retval );
+    if ( retval != PAM_SUCCESS )
+	Log_dbg( LOG_DBG_AUTH, "pam_end failed: %s",
+		 pam_strerror( pamh, retval ) );
+    pamh = NULL;
+
+    /*
+     * For completeness set euid back to original value, though it'll
+     * probably be set again by Auth_dropPrivs.
+     */
+    if ( seteuid( oldEuid ) < 0 )
+	Log_err( "Cannot set euid back to %d: %s",
+		 oldEuid, strerror( errno ) );
+}
+
+#else
+
+/*
+ * No PAM, so provide a simple alternative.
+ *
+ * USERSFILE is a simple plain-text file consisting of username password
+ * pairs, one pair per line. Comments are prefixed by '#'. Blank lines
+ * are ignored.
+ *
+ * By way of a simple security check, the users file MUST be only
+ * readable and writable by the owner.
+ */
+
+#define	AUTH_MAX_TRIES		3
+
+static int authTries = 0;
+
+static enum AuthResult
+file_authenticate( const char *user, const char *pass )
+{
+    Str file, line;
+    FILE *f;
+    struct stat statBuf;
+    enum AuthResult res = AUTH_FAILED;
+
+    Utl_cpyStr( file, USERSFILE );
+    if ( stat( file, &statBuf ) < 0 )
+    {
+	Log_err( "Cannot read %s (%s)", file, strerror( errno ) );
+	return AUTH_ERROR;
+    }
+    if ( !S_ISREG( statBuf.st_mode ) )
+    {
+	Log_err( "%s must be a regular file, not a link", file );
+	return AUTH_ERROR;
+    }
+    if ( ( statBuf.st_mode & ( S_IRWXG | S_IRWXO ) ) != 0 )
+    {
+	Log_err( "%s must be readable only by its owner", file );
+	return AUTH_ERROR;
+    }
+    
+    if ( ! ( f = fopen( file, "r" ) ) )
+    {
+        Log_err( "Cannot read %s (%s)", file, strerror( errno ) );
+        return AUTH_ERROR;
+    }
+    while ( res == AUTH_FAILED && fgets( line, MAXCHAR, f ) )
+    {
+	Str theUser, thePass;
+	char *p;
+	
+        p = Utl_stripWhiteSpace( line );
+	Utl_stripComment( p );
+
+	if ( *p == '\0' )
+	    continue;
+	
+	if ( sscanf( p, MAXCHAR_FMT " " MAXCHAR_FMT, theUser, thePass ) != 2 )
+	{
+	    res = AUTH_ERROR;
+	    Log_err( "Badly formatted line %s in %s", p, file );
+	    break;
+	}
+
+	if ( strcmp( user, theUser ) == 0 )
+	{
+	    if ( strcmp( pass, thePass ) == 0 )
+		res = AUTH_OK;
+	    break;
+	}
+    }
+
+    fclose( f );
+
+    if ( res == AUTH_FAILED )
+    {
+	authTries++;
+	sleep( authTries * authTries );
+	if ( authTries >= AUTH_MAX_TRIES )
+	    res = AUTH_DISCONNECT;
+    }
+
+    return res;
+}
+
+#endif	/* USE_PAM */
+#endif /* USE_AUTH */
+
+/* Open authentication session. */
+Bool
+Auth_open( void )
+{
+#if USE_AUTH
+#if USE_PAM
+    return PAM_open();
+#else
+    return TRUE;
+#endif    
+#else
+    return TRUE;
+#endif
+}
+
+/* Authenticate a user and password. */
+enum AuthResult
+Auth_authenticate( const char *user, const char *pass )
+{
+#if USE_AUTH
+#if USE_PAM
+    return PAM_authenticate( user, pass );
+#else
+    return file_authenticate( user, pass );
+#endif    
+#else
+    UNUSED(user);
+    UNUSED(pass);
+    
+    return TRUE;
+#endif    
+}
+
+/* Authentication session now closed. */
+void
+Auth_close( void )
+{
+#if USE_AUTH && USE_PAM
+    PAM_close();
+#endif    
+}
+
+static uid_t noffleUid = (uid_t) -1;
+static gid_t noffleGid= (gid_t) -1;
+static Bool adminUser = FALSE;
+
+/* Check we have appropriate privs for authentication. */
+Bool
+Auth_checkPrivs( void )
+{
+    uid_t euid;
+    gid_t egid;
+    uid_t ruid;
+    struct passwd* pwnam;
+    struct group* grnam;
+
+    euid = geteuid();
+    egid = getegid();
+    
+    pwnam = getpwnam( Cfg_noffleUser() );
+    if ( pwnam == NULL )
+    {
+	Log_err( "Noffle user %s is not a known user", Cfg_noffleUser() );
+	return FALSE;
+    }
+    noffleUid = pwnam->pw_uid;
+
+    grnam = getgrnam( Cfg_noffleGroup() );
+    if ( grnam == NULL )
+    {
+	Log_err( "Noffle group %s is not a known group", Cfg_noffleGroup() );
+	return FALSE;
+    }
+    noffleGid = grnam->gr_gid;
+
+    ruid = getuid();
+    adminUser = ( ruid == 0 || ruid == noffleUid );
+    
+    /*
+     * If we're really root, we will set the privs we require later. Otherwise
+     * we need to check that everything is as it should be.
+     */
+    if ( ruid != 0 )
+    {
+#if USE_AUTH && USE_PAM
+	if( Cfg_needClientAuth() )
+	{
+	    Log_err( "Noffle must run as root to use PAM authentication" );
+	    return FALSE;
+	}
+#endif
+    
+	if ( noffleUid != euid )
+	{
+	    Log_err( "Noffle needs to run as root or user %s", Cfg_noffleUser() );
+	    return FALSE;
+	}
+
+	if ( noffleGid != egid )
+	{
+	    Log_err( "Noffle needs to run as root or as group %s",
+		     Cfg_noffleGroup() );
+	    return FALSE;
+	}
+    }
+    
+    return TRUE;
+}
+
+/*
+ * See if we should be permitted admin access. Admins can do anything,
+ * non-admins can only read articles, list groups and post.
+ *
+ * This must be called after Auth_checkPrivs.
+ */
+Bool
+Auth_admin( void )
+{
+    ASSERT( noffleUid != (uid_t) -1 && noffleGid != (gid_t) -1 );
+
+    return adminUser;
+}
+
+
+/*
+ * Drop any privs required for authentication.
+ *
+ * Must be called AFTER Auth_checkPrivs.
+ */
+Bool
+Auth_dropPrivs( void )
+{
+    uid_t euid;
+
+    ASSERT( noffleUid != (uid_t) -1 && noffleGid != (gid_t) -1 );
+
+    /*
+     * We only need to drop privs if we're currently root. We
+     * should have already checked we're the news user on startup.
+     */
+    euid = geteuid();
+    if ( euid != 0 )
+	return TRUE;
+
+    if ( setgid( noffleGid ) != 0 )
+    {
+	Log_err( "Can't set group %s: %s",
+		 Cfg_noffleGroup(), strerror( errno ) );
+	return FALSE;
+    }
+
+    if ( setuid( noffleUid ) != 0 )
+    {
+	Log_err( "Can't set user to %s: %s",
+		 Cfg_noffleUser(), strerror( errno ) );
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/authenticate.h	Fri Jan 10 23:25:45 2003 +0000
@@ -0,0 +1,40 @@
+/*
+  authenticate.h
+
+  Do client authentication
+
+  $Id: authenticate.h 420 2003-01-10 23:25:45Z bears $
+*/
+
+#ifndef AUTHENTICATE_H
+#define AUTHENTICATE_H
+
+#include "common.h"
+
+enum AuthResult { AUTH_ERROR, AUTH_DISCONNECT, AUTH_FAILED, AUTH_OK };
+
+/* Authenticate a user and password. */
+enum AuthResult
+Auth_authenticate( const char *user, const char *pass );
+
+/* Open authentication session. */
+Bool
+Auth_open( void );
+
+/* Authentication session now closed. */
+void
+Auth_close( void );
+
+/* Check we have appropriate privs for authentication. */
+Bool
+Auth_checkPrivs( void );
+
+/* Are are privs sufficient only for admin access? */
+Bool
+Auth_admin( void );
+
+/* Drop any privs required for authentication. */
+Bool
+Auth_dropPrivs( void );
+
+#endif
--- a/src/noffle.c	Fri Jan 10 23:11:43 2003 +0000
+++ b/src/noffle.c	Fri Jan 10 23:25:45 2003 +0000
@@ -10,7 +10,7 @@
   received for some seconds (to allow multiple clients connect at the same
   time).
 
-  $Id: noffle.c 413 2002-12-27 21:48:25Z bears $
+  $Id: noffle.c 420 2003-01-10 23:25:45Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -20,12 +20,16 @@
 #include <ctype.h>
 #include <errno.h>
 #include <signal.h>
+#include <string.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <syslog.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "common.h"
+#include "authenticate.h"
 #include "client.h"
-#include "common.h"
 #include "content.h"
 #include "control.h"
 #include "configfile.h"
@@ -227,11 +231,11 @@
                 || Wld_match( serv, noffle.serverPattern ) )
             if ( Fetch_init( serv ) )
             {
-	        int stat = STAT_OK;
+	        int status = STAT_OK;
 	    
                 if ( noffle.queryGrps )
-                    stat = Client_getGrps();
-                if ( stat == STAT_OK && noffle.queryDsc )
+                    status = Client_getGrps();
+                if ( status == STAT_OK && noffle.queryDsc )
                     Client_getDsc();
                 Fetch_close();
             }
@@ -339,7 +343,7 @@
 		    Str xgrp;
 		    int no;
 
-		    if ( sscanf( xref, "%s:%d", xgrp, &no ) != 2 )
+		    if ( sscanf( xref, MAXCHAR_FMT ":%d", xgrp, &no ) != 2 )
 		    {
 			/* Malformed xref - leave article just in case */
 			Log_err( "Malformed Xref: entry in %s: %s",
@@ -552,6 +556,25 @@
     fprintf( stderr, "%s", msg );
 }
 
+    
+/* Check we are 'root' or the noffle user (usually 'news') */
+static Bool
+checkCurrentUser( void )
+{
+    if ( ! Auth_checkPrivs() )
+	return FALSE;
+    
+    /*
+     * If we're noffle.lockAtStartup, we need to drop privs now.
+     * Otherwise we're a server, and privs get dropped after authentication.
+     */
+    if ( noffle.lockAtStartup )
+	if ( ! Auth_dropPrivs() )
+	    return FALSE;
+    
+    return TRUE;
+}
+
 /*
   Check file ownership and permissions.
   This assumes we have cd'd to the spool directory.
@@ -559,6 +582,16 @@
 static Bool
 checkFileOwnership( void )
 {
+    Str confFile;
+    struct stat statBuf;
+    
+    Utl_cpyStr( confFile, CONFIGFILE );
+    if ( stat( confFile, &statBuf ) == 0 )
+    {
+	if ( ( statBuf.st_mode & S_IROTH ) != 0 )
+	    Log_inf( "Security warning: %s is globally readable." );
+    }
+    
     return TRUE;
 }
 
@@ -589,9 +622,13 @@
 initNoffle( void )
 {
     Log_init( "noffle", noffle.lockAtStartup, LOG_NEWS );
+
     Cfg_read();
     Log_dbg( LOG_DBG_NOFFLE, "NOFFLE version %s", Cfg_version() );
 
+    if ( ! checkCurrentUser() )
+	return FALSE;
+    
     /* cd to the spool directory */
     if ( chdir( Cfg_spoolDir() ) != 0 )
     {
@@ -798,6 +835,9 @@
     return res;
 }
 
+/* Options available to ordinary users, as opposed to administrators. */
+static const char* USER_OPTIONS = "adghlpRv";
+
 int main ( int argc, char **argv )
 {
     int c, result;
@@ -814,6 +854,9 @@
     signal( SIGTERM, logSignal );
     signal( SIGPIPE, logSignal );
 
+    /* Set umask, just in case. */
+    umask(022);
+
     /* Find last component of command name. */
     cmdname = argv[0];
     p = strrchr( cmdname, '/' );
@@ -827,7 +870,7 @@
     if ( strcmp( cmdname, "inews" ) == 0 )
 	return doInews( argc, argv );
 
-    c = -1;
+    c = 'h';
     if ( *argv != NULL )
     {
 	c = getArgLetter( *argv );
@@ -835,8 +878,6 @@
 	argc--;
     }
 
-    noffle.lockAtStartup = ! ( c == 'r' || c == 'h' );
-
     /*
       If they asked for help, give it before there's a possibility
       we could fail on init.
@@ -847,8 +888,17 @@
 	return EXIT_SUCCESS;
     }
 
+    noffle.lockAtStartup = ! ( c == 'r' );
+
     if ( ! initNoffle() )
         return EXIT_FAILURE;
+
+    if ( ! Auth_admin() && strchr( USER_OPTIONS, c ) == NULL )
+    {
+	fprintf( stderr, "You must be a news administrator to do that.\n" );
+	return EXIT_FAILURE;
+    }
+    
     result = EXIT_SUCCESS;
     switch ( c )
     {
@@ -904,10 +954,6 @@
     case 'g':
         doGrps();
         break;
-    case -1:
-    case 'h':
-        printUsage();
-        break;
     case 'l':
         doList();
         break;
--- a/src/server.c	Fri Jan 10 23:11:43 2003 +0000
+++ b/src/server.c	Fri Jan 10 23:25:45 2003 +0000
@@ -1,7 +1,7 @@
 /*
   server.c
 
-  $Id: server.c 403 2002-11-10 11:32:17Z bears $
+  $Id: server.c 420 2003-01-10 23:25:45Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -26,6 +26,7 @@
 #include <stdarg.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include "authenticate.h"
 #include "client.h"
 #include "common.h"
 #include "configfile.h"
@@ -49,6 +50,12 @@
 #include "wildmat.h"
 #include "portable.h"
 
+enum AuthState {
+    NEED_USER,
+    NEED_PASS,
+    AUTH_DONE
+};
+
 struct
 {
     Bool running;
@@ -58,18 +65,32 @@
     DynStr *reply;
     Bool eotAfterReply;
     Bool groupReady;
-} server = { FALSE, 0L, 0, "", NULL, FALSE, FALSE };
+    enum AuthState auth;
+    char *user;
+} server = {
+    FALSE,		/* running */
+    0L,			/* lastServerOpen */
+    0,			/* artPtr */
+    "",			/* grp */
+    NULL,		/* reply */
+    FALSE,		/* eotAfterReply */
+    FALSE,		/* groupReady */
+    NEED_USER,		/* auth */
+    NULL		/* user */
+};
 
 typedef struct Cmd
 {
     const char *name;
     const char *syntax;
+    Bool needAuth;
     /* Returns false, if quit cmd */
     Bool (*cmdProc)( char *arg, const struct Cmd *cmd );
 }
 Cmd;
 
 static Bool doArt( char *arg, const Cmd *cmd );
+static Bool doAuthinfo( char *arg, const Cmd *cmd );
 static Bool doBody( char *arg, const Cmd *cmd );
 static Bool doGrp( char *arg, const Cmd *cmd );
 static Bool doHead( char *arg, const Cmd *cmd );
@@ -96,27 +117,28 @@
 
 Cmd commands[] =
 {
-    { "article", "ARTICLE [msg-id|n]", &doArt },
-    { "body", "BODY [msg-id|n]", &doBody },
-    { "head", "HEAD [msg-id|n]", &doHead },
-    { "group", "GROUP grp", &doGrp },
-    { "help", "HELP", &doHelp },
-    { "ihave", "IHAVE (ignored)", &doIhave },
-    { "last", "LAST", &doLast },
+    { "article", "ARTICLE [msg-id|n]", TRUE, &doArt },
+    { "authinfo", "AUTHINFO USER username|PASS password", FALSE, &doAuthinfo },
+    { "body", "BODY [msg-id|n]", TRUE, &doBody },
+    { "head", "HEAD [msg-id|n]", TRUE, &doHead },
+    { "group", "GROUP grp", TRUE, &doGrp },
+    { "help", "HELP", FALSE, &doHelp },
+    { "ihave", "IHAVE (ignored)", TRUE, &doIhave },
+    { "last", "LAST", TRUE, &doLast },
     { "list", "LIST [ACTIVE [pat]]|ACTIVE.TIMES [pat]|"
-      "EXTENSIONS|NEWSGROUPS [pat]|OVERVIEW.FMT", &doList },
-    { "listgroup", "LISTGROUP grp", &doListgrp },
-    { "mode", "MODE (ignored)", &doMode },
-    { "newgroups", "NEWGROUPS [xx]yymmdd hhmmss [GMT]", &doNewgrps },
-    { "newnews", "NEWNEWS (not implemented)", &notImplemented },
-    { "next", "NEXT", &doNext },
-    { "post", "POST", &doPost },
-    { "quit", "QUIT", &doQuit },
-    { "slave", "SLAVE (ignored)", &doSlave },
-    { "stat", "STAT [msg-id|n]", &doStat },
-    { "xhdr", "XHDR over-field [msg-id|m[-[n]]]", &doXhdr },
-    { "xpat", "XPAT over-field msg-id|m[-[n]] pat", &doXpat },
-    { "xover", "XOVER [m[-[n]]]", &doXOver }
+      "EXTENSIONS|NEWSGROUPS [pat]|OVERVIEW.FMT", TRUE, &doList },
+    { "listgroup", "LISTGROUP grp", TRUE, &doListgrp },
+    { "mode", "MODE (ignored)", FALSE, &doMode },
+    { "newgroups", "NEWGROUPS [xx]yymmdd hhmmss [GMT]", TRUE, &doNewgrps },
+    { "newnews", "NEWNEWS (not implemented)", TRUE, &notImplemented },
+    { "next", "NEXT", TRUE, &doNext },
+    { "post", "POST", TRUE, &doPost },
+    { "quit", "QUIT", FALSE, &doQuit },
+    { "slave", "SLAVE (ignored)", TRUE, &doSlave },
+    { "stat", "STAT [msg-id|n]", TRUE, &doStat },
+    { "xhdr", "XHDR over-field [msg-id|m[-[n]]]", TRUE, &doXhdr },
+    { "xpat", "XPAT over-field msg-id|m[-[n]] pat", TRUE, &doXpat },
+    { "xover", "XOVER [m[-[n]]]", TRUE, &doXOver }
 };
 
 /*
@@ -664,6 +686,102 @@
 }
 
 static Bool
+doAuthinfo( char *line, const Cmd *cmd )
+{
+#if USE_AUTH
+    Str s, arg;
+    const char *data;
+
+    if ( ! Cfg_needClientAuth() )
+    {
+	putStat( STAT_AUTH_REJECTED, "Authentication not required" );
+	return TRUE;
+    }
+
+    if ( sscanf( line, MAXCHAR_FMT, s ) != 1 )
+    {
+    badsyntax:	
+	if ( server.auth != AUTH_DONE )
+	    server.auth = NEED_USER;
+	putSyntax( cmd );
+    }
+    else
+    {
+	Utl_toLower( s );
+	Utl_cpyStr( arg, Utl_restOfLn( line, 1 ) );
+	data = Utl_stripWhiteSpace( arg );
+
+	if ( strcmp( "user", s ) != 0 && strcmp( "pass", s ) != 0 )
+	    goto badsyntax;
+	
+	if ( strcmp( "user", s ) == 0 && server.auth == NEED_USER )
+	{
+	    if ( server.user != NULL )
+		free( server.user );
+	    Utl_allocAndCpy( &server.user, data );
+	    server.auth = NEED_PASS;
+	    putStat( STAT_MORE_AUTH_REQUIRED, "More authentication required" );
+	}
+	else if ( strcmp( "pass", s ) == 0 && server.auth == NEED_PASS )
+	{
+	    enum AuthResult authRes = Auth_authenticate( server.user, data );
+	    char *p;
+
+	    /* Zap the password */
+	    for ( p = line; *p != '\0'; p++ )
+		*p = 'X';
+	    
+	    switch ( authRes )
+	    {
+	    case AUTH_OK:
+		server.auth = AUTH_DONE;
+		putStat( STAT_AUTH_ACCEPTED, "Authentication accepted" );
+		Log_inf( "User %s authenticated", server.user );
+		break;
+
+	    case AUTH_FAILED:
+		server.auth = NEED_USER;
+		putStat( STAT_NO_PERMISSION, "No permission");
+		Log_dbg( LOG_DBG_AUTH, "User %s password %s rejected",
+			 server.user, data );
+		break;
+
+	    case AUTH_DISCONNECT:
+		putStat( STAT_NO_PERMISSION, "No permission - disconnecting" );
+		Log_dbg( LOG_DBG_AUTH,
+			 "User %s password %s rejected - disconnecting",
+			 server.user, data );
+		return FALSE;
+		
+	    default:	/* AUTH_ERROR */
+		putStat( STAT_PROGRAM_FAULT, "Authentication program error" );
+		Log_dbg( LOG_DBG_AUTH,
+			 "Error authenticating User %s password %s",
+			 server.user, data );
+		return FALSE;
+	    }
+	}
+	else
+	{
+	    if ( server.auth == AUTH_DONE )
+		putStat( STAT_AUTH_REJECTED, "Reauthentication not possible" );
+	    else
+	    {
+		putStat( STAT_AUTH_REJECTED, "Authentication rejected" );
+		server.auth = NEED_USER;
+	    }
+	}
+    }
+#else
+    UNUSED( line );
+    UNUSED( cmd );
+    
+    putStat( STAT_AUTH_REJECTED, "Authentication not possible" );
+#endif    
+    return TRUE;
+}
+
+static Bool
 doHelp( char *arg, const Cmd *cmd )
 {
     unsigned int i;
@@ -839,7 +957,7 @@
     else
     {
         Utl_toLower( s );
-        strcpy( arg, Utl_restOfLn( line, 1 ) );
+        Utl_cpyStr( arg, Utl_restOfLn( line, 1 ) );
         pat = Utl_stripWhiteSpace( arg );
         if ( pat[ 0 ] == '\0' )
             pat = "*";
@@ -1437,7 +1555,7 @@
 
 /* Parse line, execute command and return FALSE, if it was the quit command. */
 static Bool
-parseAndExecute( Str line )
+parseAndExecute( Str line, Bool authDone )
 {
     unsigned int i, n;
     Cmd *c;
@@ -1447,11 +1565,20 @@
     if ( sscanf( line, MAXCHAR_FMT, s ) == 1 )
     {
         Utl_toLower( s );
-        strcpy( arg, Utl_restOfLn( line, 1 ) );
+        Utl_cpyStr( arg, Utl_restOfLn( line, 1 ) );
         n = sizeof( commands ) / sizeof( commands[ 0 ] );
         for ( i = 0, c = commands; i < n; ++i, ++c )
             if ( strcmp( c->name, s ) == 0 )
             {
+#if USE_AUTH
+		if ( c->needAuth && ! authDone )
+		{
+		    putStat( STAT_AUTH_REQUIRED, "Authentication required" );
+		    return TRUE;
+		}
+#else
+		UNUSED( authDone );
+#endif		     
                 ret = c->cmdProc( Utl_stripWhiteSpace( arg ), c );
                 return ret;
             }
@@ -1501,6 +1628,63 @@
     Str line;
 
     putWelcome();
+
+#if USE_AUTH
+    /*
+     * If authentication is required, we issue the welcome message and
+     * go into a command loop that doesn't open the databases and just
+     * accepts authentication commands. Once successfully authenticated,
+     * we drop root privs (if we have them - they are needed for PAM
+     * authentication to work) and proceed to the normal loop.
+     */
+    if ( Cfg_needClientAuth() )
+    {
+	if ( ! Auth_open() )
+	{
+	    initOutput();
+	    putFatal( "Cannot open authorisation" );
+	    sendOutput();
+	    return;
+	}
+
+	done = FALSE;
+	while ( ! done )
+	{
+	    if ( Prt_getLn( line, stdin, -1 ) )
+	    {
+		initOutput();
+
+		if ( ! parseAndExecute( line, FALSE ) )
+		    done = TRUE;
+
+		if ( server.auth == AUTH_DONE )
+		    done = TRUE;
+
+		sendOutput();
+	    }
+	    else
+	    {
+		Log_inf( "Client disconnected. Terminating." );
+		done = TRUE;
+	    }
+	}
+
+	Auth_close();
+
+	/* Did we finish because we successfully authenticated? */
+	if ( server.auth != AUTH_DONE )
+	    return;
+    }
+#endif
+
+    if ( ! Auth_dropPrivs() )
+    {
+	initOutput();
+	putFatal( "Cannot set user privs" );
+	sendOutput();
+	return;
+    }
+    
     done = FALSE;
     while ( ! done )
     {
@@ -1515,7 +1699,7 @@
 	    }
 	    else
 	    {
-		if ( ! parseAndExecute( line ) )
+		if ( ! parseAndExecute( line, TRUE ) )
 		    done = TRUE;
 	    }