Imported vmailmgr-0.96.9 vmailmgr-0.96.9
author"Tomas Zeman <tzeman@volny.cz>"
Wed, 16 Jan 2008 22:39:43 +0100
changeset 0 6f7a81934006
child 1 30113bfbe723
Imported vmailmgr-0.96.9
AUTHORS
COPYING
ChangeLog
INSTALL
Makefile.am
Makefile.in
NEWS
README
TODO
acconfig.h
acinclude.m4
aclocal.m4
authenticate/Makefile.am
authenticate/Makefile.in
authenticate/authvlib.cc
authenticate/authvlib.h
authenticate/authvmailmgr.cc
authenticate/checkvpw.1
authenticate/checkvpw.cc
authenticate/checkvpw.html
authenticate/checkvpw.pod
authenticate/vauthenticate.1
authenticate/vauthenticate.cc
authenticate/vauthenticate.html
authenticate/vauthenticate.pod
cgi/Makefile.am
cgi/Makefile.in
cgi/listvdomain.cc
cgi/listvdomain.html
cgi/vaddalias.cc
cgi/vaddalias.html
cgi/vadduser.cc
cgi/vadduser.html
cgi/vchalias.html
cgi/vchattr.cc
cgi/vchattr.html
cgi/vchforwards.cc
cgi/vchforwards.html
cgi/vdeluser.cc
cgi/vdeluser.html
cgi/vpasswd.cc
cgi/vpasswd.html
commands/Makefile.am
commands/Makefile.in
commands/allvpasswd2cdb
commands/listvdomain.1
commands/listvdomain.cc
commands/listvdomain.html
commands/listvdomain.pod
commands/vaddalias
commands/vadduser.1
commands/vadduser.cc
commands/vadduser.html
commands/vadduser.pod
commands/vaddusers.cc
commands/vchattr.1
commands/vchattr.cc
commands/vchattr.html
commands/vchattr.pod
commands/vcheckquota.1
commands/vcheckquota.cc
commands/vcheckquota.html
commands/vcheckquota.pod
commands/vchforwards.1
commands/vchforwards.cc
commands/vchforwards.html
commands/vchforwards.pod
commands/vcommand.cc
commands/vcommand.h
commands/vconf2dir
commands/vdeliver.1
commands/vdeliver.cc
commands/vdeliver.html
commands/vdeliver.pod
commands/vdeluser.1
commands/vdeluser.cc
commands/vdeluser.html
commands/vdeluser.pod
commands/vpasswd.1
commands/vpasswd.cc
commands/vpasswd.html
commands/vpasswd.pod
commands/vpasswd2cdb.1
commands/vpasswd2cdb.cc
commands/vpasswd2cdb.html
commands/vpasswd2cdb.pod
commands/vpasswd2db.1
commands/vpasswd2db.cc
commands/vpasswd2db.html
commands/vpasswd2db.pod
commands/vpasswds.1
commands/vpasswds.cc
commands/vpasswds.html
commands/vpasswds.pod
commands/vpopbull.1
commands/vpopbull.cc
commands/vpopbull.html
commands/vpopbull.pod
commands/vrehash.1
commands/vrehash.cc
commands/vrehash.html
commands/vrehash.pod
commands/vsetup.1
commands/vsetup.cc
commands/vsetup.html
commands/vsetup.pod
config.h.in
configure
configure.in
daemon/Makefile.am
daemon/Makefile.in
daemon/adduser2.cc
daemon/autoresponse.cc
daemon/chattr.cc
daemon/check.cc
daemon/command.cc
daemon/command.h
daemon/daemon.h
daemon/deluser.cc
daemon/dispatch.cc
daemon/listdomain.cc
daemon/log.cc
daemon/log.h
daemon/lookup.cc
daemon/main.cc
daemon/state.cc
daemon/state.h
daemon/vmailmgrd.8
daemon/vmailmgrd.html
daemon/vmailmgrd.pod
doc/ChangeLog-pre-0.70
doc/ChangeLog-pre-vmailmgr
doc/ChangeLog.html
doc/FAQ.html
doc/FAQ.sgml
doc/FAQ.txt
doc/HOWTO.html
doc/HOWTO.sgml
doc/HOWTO.txt
doc/Makefile.am
doc/Makefile.in
doc/NEWS.html
doc/YEAR2000
doc/changelog2html.pl
doc/configuration.html
doc/configuration.texi
doc/configuration.txt
doc/news2html.pl
doc/protocol.txt
doc/record-format.txt
doc/translation.fig
doc/translation.ps
doc/vmailmgr-cgi.html
doc/vmailmgr-cgi.texi
doc/vmailmgr-cgi.txt
doc/vmailmgr.7
doc/vmailmgr.html
doc/vmailmgr.pod
install-sh
lib/Makefile.am
lib/Makefile.in
lib/ac/dirent.h
lib/ac/time.h
lib/ac/wait.h
lib/cdb++/ChangeLog
lib/cdb++/Makefile.am
lib/cdb++/Makefile.in
lib/cdb++/cdb++.h
lib/cdb++/cdb_get.cc
lib/cdb++/cdb_getrec.cc
lib/cdb++/cdb_make.cc
lib/cdb++/cdb_reader.cc
lib/cdb++/cdb_writer.cc
lib/cdb++/cdbtest.cc
lib/cdb++/datum.cc
lib/cdb++/datum.h
lib/cdb++/internal.h
lib/cgi/ChangeLog
lib/cgi/Makefile.am
lib/cgi/Makefile.in
lib/cgi/cgi-args.cc
lib/cgi/cgi-args.h
lib/cgi/cgi-base.cc
lib/cgi/cgi-base.h
lib/cli/ChangeLog
lib/cli/Makefile.am
lib/cli/Makefile.in
lib/cli/cli.h
lib/cli/cli2pod.pl
lib/cli/clitest.cc
lib/cli/main.cc
lib/cli/messages.cc
lib/config/Makefile.am
lib/config/Makefile.am.in
lib/config/Makefile.in
lib/config/_autoresponse_dir.cc
lib/config/_autoresponse_file.cc
lib/config/_bulletin_dir.cc
lib/config/_default_expiry.cc
lib/config/_default_hardquota.cc
lib/config/_default_maildir.cc
lib/config/_default_msgcount.cc
lib/config/_default_msgsize.cc
lib/config/_default_softquota.cc
lib/config/_default_username.cc
lib/config/_error_maildir.cc
lib/config/_global_bulletin_dir.cc
lib/config/_maildir_arg_str.cc
lib/config/_password_file.cc
lib/config/_postmaster_aliases.cc
lib/config/_postmaster_email.cc
lib/config/_qmail_root.cc
lib/config/_separators.cc
lib/config/_socket_file.cc
lib/config/_user_dir.cc
lib/config/_user_dir_bits.cc
lib/config/_user_dir_slices.cc
lib/config/build-config.sh
lib/config/config_read.cc
lib/config/configio.h
lib/config/configrc.cc
lib/config/configrc.h
lib/config/configrc.h.in
lib/config/configrc.in
lib/config/configvar.in
lib/config/read_dir.cc
lib/config/read_list.cc
lib/config/read_str.cc
lib/config/read_uns.cc
lib/config/showvconfig.cc
lib/config/showvconfig.cc.in
lib/courier-authlib/COPYING
lib/courier-authlib/Makefile.am
lib/courier-authlib/Makefile.in
lib/courier-authlib/README
lib/courier-authlib/auth.h
lib/courier-authlib/authexit.c
lib/courier-authlib/authmod.c
lib/courier-authlib/authmod.h
lib/courier-authlib/authmodfail.c
lib/courier-authlib/authwait.h
lib/courier-authlib/chain.c
lib/courier-authlib/changeuidgid.c
lib/courier-authlib/copyargv.c
lib/courier-authlib/success.c
lib/fdbuf/ChangeLog
lib/fdbuf/Makefile.am
lib/fdbuf/Makefile.in
lib/fdbuf/fdbuf.cc
lib/fdbuf/fdbuf.h
lib/fdbuf/fdbuf_copy.cc
lib/fdbuf/fdibuf.cc
lib/fdbuf/fdibuf.h
lib/fdbuf/fdibuf_mystring.cc
lib/fdbuf/fdibuf_netstring.cc
lib/fdbuf/fdobuf.cc
lib/fdbuf/fdobuf.h
lib/fdbuf/fdobuf_chownmod.cc
lib/fdbuf/fdobuf_seek.cc
lib/fdbuf/fdobuf_signed.cc
lib/fdbuf/fdobuf_unsigned.cc
lib/mergelib.sh
lib/misc/Makefile.am
lib/misc/Makefile.in
lib/misc/autodelete.h
lib/misc/crc32.cc
lib/misc/crc32.h
lib/misc/crc_hash.h
lib/misc/debug.h
lib/misc/exec.cc
lib/misc/exec.h
lib/misc/hash_table.h
lib/misc/itoa.cc
lib/misc/itoa.h
lib/misc/keystrlist.cc
lib/misc/krbauth.c
lib/misc/list_table.cc
lib/misc/list_table.h
lib/misc/lookup.h
lib/misc/lookup_baseuser.cc
lib/misc/lookup_domain.cc
lib/misc/maildir.cc
lib/misc/maildir.h
lib/misc/map_table.cc
lib/misc/map_table.h
lib/misc/md5-crypt.c
lib/misc/md5.c
lib/misc/md5.h
lib/misc/passwdfn.cc
lib/misc/passwdfn.h
lib/misc/pwcrypt.cc
lib/misc/pwcrypt.h
lib/misc/pwentry.cc
lib/misc/pwentry.h
lib/misc/pwentry_auth.cc
lib/misc/pwentry_export_env.cc
lib/misc/pwentry_table.cc
lib/misc/pwentry_table.h
lib/misc/response.h
lib/misc/response_message.cc
lib/misc/response_read.cc
lib/misc/response_write.cc
lib/misc/server.cc
lib/misc/server.h
lib/misc/server_call0.cc
lib/misc/server_call1.cc
lib/misc/server_call2.cc
lib/misc/server_call3.cc
lib/misc/server_call4.cc
lib/misc/server_call5.cc
lib/misc/server_call6.cc
lib/misc/stat_fns.h
lib/misc/strlist.cc
lib/misc/strlist.h
lib/misc/strlist_read.cc
lib/misc/strlist_write.cc
lib/misc/strtou.c
lib/misc/strtou.h
lib/misc/un.h
lib/misc/utoa.cc
lib/misc/utoa.h
lib/mystring/ChangeLog
lib/mystring/Makefile.am
lib/mystring/Makefile.in
lib/mystring/append.cc
lib/mystring/assign.cc
lib/mystring/count.cc
lib/mystring/fdobuf.cc
lib/mystring/find_first_ch.cc
lib/mystring/find_first_of.cc
lib/mystring/find_last_ch.cc
lib/mystring/find_last_of.cc
lib/mystring/iter.cc
lib/mystring/iter.h
lib/mystring/join.cc
lib/mystring/join.h
lib/mystring/lower.cc
lib/mystring/lstrip.cc
lib/mystring/mystring.cc
lib/mystring/mystring.h
lib/mystring/rep.cc
lib/mystring/rep.h
lib/mystring/rstrip.cc
lib/mystring/strip.cc
lib/mystring/sub.cc
lib/mystring/subst.cc
lib/mystring/trace.h
lib/mystring/upper.cc
lib/vdomain/Makefile.am
lib/vdomain/Makefile.in
lib/vdomain/chattr.cc
lib/vdomain/deluser.cc
lib/vdomain/lookup.cc
lib/vdomain/set.cc
lib/vdomain/userdir.cc
lib/vdomain/validate.cc
lib/vdomain/vdomain.cc
lib/vdomain/vdomain.h
lib/vpwentry/Makefile.am
lib/vpwentry/Makefile.in
lib/vpwentry/auth.cc
lib/vpwentry/decode.cc
lib/vpwentry/defaults.cc
lib/vpwentry/export_env.cc
lib/vpwentry/from.cc
lib/vpwentry/from_old.cc
lib/vpwentry/from_ver1.cc
lib/vpwentry/from_ver2.cc
lib/vpwentry/to.cc
lib/vpwentry/vpwentry.cc
lib/vpwentry/vpwentry.h
lib/vpwtable/Makefile.am
lib/vpwtable/Makefile.in
lib/vpwtable/cdb_del.cc
lib/vpwtable/cdb_exists.cc
lib/vpwtable/cdb_getbyname.cc
lib/vpwtable/cdb_put.cc
lib/vpwtable/cdb_read.cc
lib/vpwtable/cdb_vpwtable.cc
lib/vpwtable/gdbm_del.cc
lib/vpwtable/gdbm_exists.cc
lib/vpwtable/gdbm_getbyname.cc
lib/vpwtable/gdbm_put.cc
lib/vpwtable/gdbm_read.cc
lib/vpwtable/gdbm_vpwtable.cc
lib/vpwtable/reader.cc
lib/vpwtable/vpwtable.h
missing
mkinstalldirs
php/Makefile.am
php/Makefile.in
php/vmail.features
php/vmail.inc
python/Makefile.am
python/Makefile.in
python/__init__.py
python/commands.py
python/config.py
python/constants.py
python/daemon.py
python/types.py
scripts/Makefile.am
scripts/Makefile.in
scripts/autoresponder.sh
scripts/vmailmgrd-log.run
scripts/vmailmgrd.init
scripts/vmailmgrd.run
stamp-h.in
vmailmgr-0.96.9.spec
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AUTHORS	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,27 @@
+Written by Bruce Guenter <bruceg@em.ca>
+
+Dan Kuykendall <dan@kuykendall.org> extended the FAQ and HOWTO and
+converted them to SGML.
+
+Mike Bell <mike@mikebell.org> has contributed the current PHP module
+and several patches.
+
+The CDB library was originally written by D.J.Bernstein <djb@pobox.com>.
+I have subsequently rewritten parts of it to better fit into C++ style
+accesses.  The only copyright notice I could find in the original
+package says:
+
+	If you want to incorporate cdb into your own packages, you can
+	just copy the code here.
+
+The MD5 Message-Digest Algorithm library was written by Ulrich Drepper
+<drepper@gnu.ai.mit.edu>, 1995, and was taken from the GNU C Library
+
+Kerberos5 support written by Nickolai Zeldovich <kolya@zepa.net>
+
+Anil Madhavapeddy <anil@recoil.org> has contributed a makefile /
+configure.in patch.
+
+Eugene Miretskiy <eugene@invision.net> contributed the original quota
+checking program, vcheckquota.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/COPYING	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ChangeLog	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,3096 @@
+2000-09-30  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* Released version 0.96.9
+
+	* python/commands.py (adduser): Fixed a typo that prevents users
+	without a mailbox from being added.
+
+2000-09-15  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* authenticate/authvlib.cc (check): Always set VUSER, even if
+	virtname is blank.
+
+2000-09-14  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* daemon/main.cc: Exit immediately if a SIGPIPE or SIGALRM is
+	caught.
+
+2000-09-12  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* pyadmin/vmailmgr_lib.py (Flag.html): Added this method to print
+	out a HTML select list with the correct item selected.
+
+	* pyadmin/vmailmgr_sessiond.py: New program set up to track
+	session status in memory instead of on disk.
+
+	* pyadmin/vmailmgr_pyadmin.py (cgi_main): Create a Context object
+	for passing in to format_page.
+
+	* pyadmin/vmailmgr_parser.py (Context): Defined this context
+	object that wraps context data.  This will be extended to stack
+	contexts.  When doing a __getitem__, if the key is not found in
+	the context dictionary, that key is evaluated as an expression
+	with the dictionary as local variables.
+	(Foreach.do_end): Pass the formatted sections to
+	stack.append_or_print instead of printing them directly.
+
+2000-09-11  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* Removed all old Python support code, replace by the new
+	"pyadmin" interface.
+
+2000-09-05  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* daemon/dispatch.cc (dispatch_cmd): Don't add "-virtuser" to
+	baseuser name if virtuser is empty.
+
+2000-09-04  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* python/vmailmgr_cgi.py.in (Session): Added prototype for new
+	class to manage session data.
+
+	* daemon/check.cc (CMD): Simplified the logic, elimited the return
+	value.  Now returns either error or OK.
+
+2000-09-01  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* doc/FAQ.sgml: Added section on long POP3 logins.
+
+2000-08-22  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* commands/vdeliver.cc (deliver_partial): Fail permanently if: the
+	open failed, EDQUOT is defined, and the error number is EDQUOT.
+
+2000-08-15  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* daemon/deluser.cc (CMD): Use new form of vdomain::deluser.
+
+	* lib/vpwtable/reader.cc (vpwtable_reader): Removed the call to
+	end here, which produced a missing reference to
+	vpwtable_reader::end.
+
+2000-08-13  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* commands/*.cc: Moved all the POD man page documentation into the
+	source files using a new CLI documentation generator.
+
+2000-08-11  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* commands/vdeluser.cc: Added an option to prevent vdeluser from
+	deleting a user with a mailbox.
+
+	* lib/vdomain/deluser.cc (deluser): Added a flag to make deluser
+	not delete users with a mailbox.
+
+	* daemon/main.cc: Fixed up some of the cli_* values.
+
+	* doc/FAQ.sgml: Added note regarding difference between vmailmgr
+	and vpopmail.
+
+	* lib/vpwtable/gdbm_read.cc (class gdbm_vpwtable_reader): Added
+	this new subclass of vpwtable_reader.
+
+	* lib/vpwtable/cdb_read.cc (class cdb_vpwtable_reader): Added this
+	new subclass of vpwtable_reader.
+	
+	* lib/vpwtable/vpwtable.h (class vpwtable_reader): Removed the
+	short-sighted conditional mess in this class with virtual methods.
+
+2000-08-10  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* Released version 0.96.8
+
+	* authenticate/authvlib.cc (set_user): Call pwentry::export_env
+	instead of doing it manually.
+
+	* lib/misc/pwentry_export_env.cc (export_env): Added this routine
+	to export USER and HOME for a real user.
+
+	* commands/vcheckquota.cc (link_softquota_message): Fixed bug in
+	multiple use of atoi.
+
+	* doc/HOWTO.sgml: Added a note on vsetup.
+
+2000-08-04  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* doc/FAQ.sgml: Added notes on location of qmail-autoresponder and
+	the CVS repository.
+
+	* daemon/autoresponse.cc (autoresponse_read): If the normal
+	autoresponse file can't be read, try the disabled file.
+	(autoresponse_status): Added status command.
+
+	* commands/vcheckquota.cc (link_softquota_message): Added code to
+	symlink in warning message if softquota fails.  This will link the
+	message in each time soft quota fails.
+
+2000-08-03  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* commands/vdeliver.cc (cli_main): Make sure to rewind stdin
+	before executing vdeliver-postdeliver.
+
+	* daemon/lookup.cc: Rewritten to output the entire virtual user
+	data instead of just the mailbox and aliases.
+
+	* commands/vcheckquota.cc: Changed many instances of "int" to
+	"unsigned".
+	(check_quota): Always check incoming message size, and check max
+	count even if no quotas apply.
+
+	* lib/misc/exec.cc (execute_one): Fixed a bug where this would
+	return the raw status value instead of WEXITSTATUS(status).
+
+2000-08-02  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* daemon/autoresponse.cc (autoresponse_write): Applied bugfix that
+	would allow disabled autoresponses to be written.
+
+2000-08-01  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* commands/vcheckquota.cc (exit_msg): Fixed typo (used to say
+	"vdeliver:").
+	(cli_main): Fixed another typo -- VUSER_MAILDIR is not set, plain
+	MAILDIR is.
+
+	* authenticate/checkvpw.cc (main): Removed call to execute
+	checkvpw-postsetuid.
+
+	* authenticate/authvlib.cc (set_user): Added a hook to execute the
+	proper presetuid script.
+	(authenticate): Added a hook to execute the proper postsetuid
+	script.
+
+2000-07-31  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* daemon/lookup.cc (lookup_and_validate): Set the "nodefault" flag
+	in vdomain::lookup to true instead of false -- it's never correct
+	to look up the default user in the daemon.
+
+2000-07-18  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* commands/vcheckquota.cc: Added this new program, originally
+	authored by Eugene Miretskiy, and subsequently modified.
+
+2000-07-17  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* doc/HOWTO.sgml, doc/FAQ.sgml: Updated documentation.
+
+2000-07-05  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* Released version 0.96.7.
+
+	* lib/vpwtable/cdb_read.cc: Added CDB support for the vpwtable
+	reader class.
+
+	* daemon/listdomain.cc (CMD_FD): Adjusted to use the new vpwtable
+	reader.
+
+	* commands/listvdomain.cc (cli_main): Adjusted to use new vpwtable
+	reader.
+
+	* lib/vpwtable/gdbm_read.cc (vpwtable_reader): Added this new
+	class to replace the stream reading support from the vpwtable
+	class.
+
+2000-07-04  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* lib/vpwtable/gdbm_getbyname.cc (getbyname): Lowercase the name
+	before retrieving it.
+
+	* commands/listvdomain.cc (cli_main): Exit with error if listing
+	an individual user fails.
+
+	* lib/vpwtable/gdbm_get.cc (start): Fixed missing gdbm_firstkey.
+
+	* commands/vpasswd2db.cc: Added new utility to convert plain text
+	password tables into whatever vpwtable format was configured.
+
+2000-06-25  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* python/vmailmgr.py.in: Added deluser and chattr commands.
+
+2000-06-24  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* doc/configuration.texi (socket-file): Reinstated this config
+	section.
+
+	* daemon/autoresponse.cc (autoresponse_delete): Added a new
+	command to delete the autoresponse data.
+
+	* lib/misc/maildir.cc (delete_directory): Renamed from
+	delete_maildir.
+
+	* daemon/autoresponse.cc (autoresponse_write): Create the
+	autoresponse directory if it does not already exist.
+
+2000-06-19  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* lib/vpwtable: Added GDBM support in the gdbm_*.cc files.
+
+	* lib/vpwtable/cdb_vpwtable.cc: Made the ".cdb" string a constant.
+
+	* lib/vpwtable: Renamed all the .cc files to "cdb_*.cc".
+
+2000-06-14  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* doc/configuration.texi: Added notes on the autoresponse
+	configuration items, removed the notes on max-fork and
+	socket-file.
+
+2000-06-13  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* daemon/main.cc (cli_main): Rewrote main to use the cli library.
+	This removes extra command line parsing code and incidentally
+	fixes a problem with random not being initialized.
+
+	* daemon/log.cc (log): Revised handling of printing PIDs.
+
+	* daemon/dispatch.cc: Removed "forkstat" command.
+
+	* daemon/main.cc: Removed support code needed to create and accept
+	connections on a UNIX domain socket, in favour of using the new
+	ucspi-unix package.
+
+2000-06-01  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* Released version 0.96.6
+
+	* commands/vdeliver.cc (cli_main): Fixed typo in order of
+	operands in call to exit_msg.
+
+	* lib/misc/map_table.cc (map_table): Lower case all keys to allow
+	for case insensitive comparisons.
+
+	* lib/misc/lookup_domain.cc (find_virtual): Fixed bug: domain
+	names are not case sensitive.
+
+2000-05-31  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* python/vmailmgr.py.in (VUser.from_binary): Fixed some bugs in
+	the conversion of flags.
+
+2000-05-25  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* python/vmailmgr_cgi.py.in (print_html): Added code to print out
+	a HTML error if the requested file could not be printed.
+	(wrap_print): Print out basename+"-success" on success, and
+	provide a default error response if the error file does not
+	exist.
+
+	* daemon/daemon.h (CMD): Removed a bogus "const" from the
+	declarations of the CMD and CMD_FD macros.
+
+	* daemon/autoresponse.cc (CMD_FD): Added proper command logging to
+	this command.
+	(CMD_FD): Fixed type -- a virtual user's password is acceptable.
+
+	* daemon/log.cc: Added a new LOG_MESSAGE constant.
+
+	* doc/FAQ.sgml: Added a brief section on how to configure
+	qmail+patches for use with vmailmgr.
+
+	* doc/configuration.texi (qmail-root): Added this missing section.
+
+2000-05-24  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* python/vmailmgr_cgi.py.in (cgi_main): Trap trying to run the
+	program outside of a CGI environment.
+
+	* python/vmailmgr.py.in (VUser): Added this class to represent the
+	data associated with a virtual user.  A special __getitem__
+	routine allows the data to be read as a dictionary.
+	(Daemon): More code reorganization in this class.
+	(listdomain): Added this command, which returns a dictionary of
+	all the users in the domain.
+	(adduser): Added this command to add a virtual user.
+	(autoresponse): Added this command, which executes the daemon
+	"autoresponse" command.
+
+	* python/vmailmgr_cgi.py.in (wrap_print): Added this new routine,
+	which wraps a call to a vmailmgr command in a try/except block,
+	and prints an output file based on the results.
+
+	* Added SGML documentation from Dan Kuykendall.
+
+2000-05-16  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* python/vmailmgr_cgi.py.in: Moved all the CGI specific
+	functionality into this new module.
+
+	* python/vmailmgr.py.in: Removed the "Response" class and turned
+	error responses into exceptions.  The server socket is not closed
+	at the end of a command to allow a listdomain command to read more
+	data after the initial response.
+
+2000-05-09  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* commands/vdeliver.cc (cli_main): Error exits from executing
+	"vdeliver-predeliver" would unconditionally result in a temporary
+	failure for qmail.  Fixed to return the actual error number to
+	qmail.
+
+2000-05-02  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* cgi/vchforwards.cc (CGI_MAIN ): Fixed an internal glitch -- the
+	new "do_enable" and "do_disable" internal variables were
+	duplicated.
+
+	* daemon/lookup.cc (lookup_and_validate): Modified to use the new
+	set_defaults method.
+
+	* commands/vchattr.cc: Make size limits refer to bytes.
+
+	* doc/configuration.texi: Indicate that size limits are in units
+	of bytes.
+
+	* commands/vadduser.cc: Make size limits refer to bytes
+	everywhere.
+
+	* commands/vsetup.cc (setup_alias): Modified to use the new
+	set_defaults method.
+
+	* commands/vpasswd2cdb.cc (getpw): Removed set_defaults call,
+	since from_record calls set_defaults after doing conversion from
+	the old format data.
+
+	* commands/vaddusers.cc (add_one): Modified to use the new
+	set_defaults method.
+
+	* lib/vpwentry/from_old.cc (from_old_record): Modified to use the
+	new set_defaults method.
+
+	* commands/vadduser.cc: Modified to use the new set_defaults
+	method.
+
+	* lib/vpwentry/defaults.cc (set_defaults): Add a flag to set the
+	creation time to either now (true) or 0 (false -- for old
+	records), as well as a flag to set the boolean flags.
+
+	* lib/misc/strtou.c: Use UINT_MAX instead of (unsigned)-1.
+
+	* lib/config/showvconfig.cc.in: Use UINT_MAX instead of
+	(unsigned)-1.
+
+	* lib/config/configrc.in: Use UINT_MAX instead of (unsigned)-1.
+
+	* lib/misc/lookup_domain.cc (find_virtual): Use UINT_MAX instead
+	of (unsigned)-1.
+
+	* lib/vpwentry/defaults.cc (set_defaults): Use UINT_MAX instead of
+	(unsigned)-1.
+
+	* lib/misc/utoa.cc (utoa): Use UINT_MAX instead of (unsigned)-1.
+
+	* lib/vpwentry/from_ver1.cc (from_ver1_record): Set the flags
+	before returning.
+
+	* lib/vpwentry/from_old.cc (from_old_record): Set the flags before
+	returning.
+
+2000-04-19  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* doc/vchattr.pod: Added note regarding personal information.
+
+	* doc/vmailmgr-cgi.texi (Top): Added note regarding personal
+	information.
+
+	* commands/vchattr.cc: Allow changing the personal information.
+
+	* lib/vdomain/chattr.cc (chattr): Added code to handle changing
+	the personal information.
+
+2000-04-18  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* doc/FAQ.texi (Does vmailmgr support IMAP?): Updated to describe
+	current status of IMAP support.
+
+	* daemon/dispatch.cc: Added autoresponse dispatch entry.
+
+	* daemon/autoresponse.cc: Added autoresponse command from Mike Bell.
+
+2000-04-14  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* Modified the spec file to put the Courier IMAP module into a
+	seperate package.
+
+	* Copied the necessary sources from Courier IMAP to build a
+	minimal stand-alone libauthmod in order to build the
+	authentication module without needing the Courier IMAP sources.
+
+2000-04-13  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* Released version 0.96.5
+
+	* doc/vchattr.pod: Wrote a man page for the vchattr command.
+
+2000-04-12  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* commands/vdeliver.cc (cli_main): Check if the account has
+	expired before delivering.
+
+	* authenticate/authvlib.cc (check): Check if the acount has
+	expired and fail if so.
+
+	* lib/vpwentry/export_env.cc (export_env): Set
+	"VUSER_MAILBOX_ENABLED" to the new flag.
+
+	* authenticate/authvlib.cc (check): If looking up the base user
+	fails, and virtual_only is set, return instead of failing hard.
+
+	* daemon/chattr.cc (CMD): Allow mailbox enabled flag to be changed
+	by virtual users.
+
+	* commands/listvdomain.cc (show_user): Print out "(disabled)" next
+	to the mailbox directory if the "is_mailbox_enabled" flag is not
+	set.
+
+	* cgi/listvdomain.cc (show_user): Adapted to using
+	vpwentry::from_record instead of vpwentry::from_ver1_record.
+
+	* lib/vpwentry/vpwentry.cc: Set the flag defaults here on creation
+	instead of in set_defaults.
+
+	* lib/vdomain/chattr.cc (chattr): Modified to use the new vpwentry
+	is_mailbox_enabled flag.
+
+	* lib/vpwentry/from_ver1.cc (from_ver1_record): Made this a
+	protected non-static method.
+
+	* lib/vpwentry/from_ver2.cc (from_ver2_record): Made this a
+	protected non-static method.
+
+	* lib/vpwentry/from_old.cc (from_old_record): Made this a
+	protected non-static method.
+
+	* lib/vpwentry/from.cc (from_record): Made this a non-static method.
+
+	* lib/vpwentry/decode.cc: Moved the common pieces from from_ver1
+	and from_ver2 into seperate routines and moved them here.
+
+	* lib/vpwentry/from_ver2.cc (from_ver2_record): Added this routine
+	to do conversions from the new binary record format.
+
+	* lib/vpwentry/to.cc (to_record): Modified to create the new
+	binary record format.
+
+	* lib/vpwentry/from_uint.cc (from_uint): Moved this routine out of
+	from_ver1.cc, as it's common to both ver1 and ver2 (and other)
+	records.
+
+	* lib/vdomain/chattr.cc: Returned the extraneous definition of
+	strtou from here.
+
+	* lib/config/read_uns.cc (read_uns): Coded to use our strtou.
+
+	* lib/misc/strtou.c (strtou): Renamed the C++ source to a C
+	source, and added a header file.  Added a null-pointer and leading
+	space check.
+
+	* lib/vpwentry/vpwentry.h (struct vpwentry ): Removed the
+	enable/disable routines and added a "is_mailbox_enabled" boolean
+	flag.
+
+2000-04-11  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* cgi/vadduser.cc (CGI_MAIN ): Added code to handle adding
+	forwarding at the same time as the user.
+
+	* lib/misc/lookup_baseuser.cc (lookup_baseuser): Modified to use
+	mystring::left instead of a hacked-up constructor call.
+
+	* cgi/vchforwards.cc (CGI_MAIN ): Added code here to handle
+	enabling and disabling the mailbox.
+
+	* commands/vchattr.cc: Added handling in this code for the new
+	flag.
+
+	* lib/vdomain/chattr.cc (chenabled): Added this function to enable
+	or disable delivery to a virtual user.
+
+	* lib/vpwentry/is_enabled.cc (is_enabled): Modified this routine
+	to return false if no mailbox path is set.
+
+	* commands/vdeliver.cc (cli_main): Handle the "enabled" flag here
+	by not doing mailbox delivery if is_enabled returns false.
+
+	* lib/vpwentry/is_enabled.cc (is_enabled): Created this routine to
+	determine if the account has been disabled.
+
+	* lib/vpwentry/disable.cc: Created routines here to enable and
+	disable an account by removing and creating a "disabled" file in
+	the virtual user's mailbox directory.
+
+	* Released version 0.96.4
+
+	* lib/misc/exec.cc (presetenv): Changed this routine to allocate a
+	new string (char*) that it never frees.  This seems to fix the
+	problems with garbage making its way into the environment.
+
+2000-04-10  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* lib/vpwentry/export_env.cc (export_env): Moved the setenv
+	routine that exported a vpwentry to this method of vpwentry.
+
+	* lib/misc/exec.cc (presetenv): Renamed "setenv" to this, to
+	prevent confusion with any built-in "setenv" functions.
+
+	* authenticate/authvmailmgr.cc: Made the user name, pass phrase,
+	and domain name into globals, to prevent their memory from being
+	deallocated prematurely.
+
+2000-04-09  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* doc/vmailmgr-cgi.texi: Adjusted this documentation to fit the
+	new CGIs.
+
+	* cgi/vaddalias.cc (CGI_MAIN ): Modified to handle a
+	comma-seperated list of destinations.
+
+	* cgi/vchforwards.cc: Renamed vchalias to this file, to match the
+	command-line program's name change.
+	(CGI_MAIN ): Modified to handle a comma-seperated list of destinations.
+
+2000-04-07  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* Updates for new mystring and fdbuf libraries.
+
+	* commands/vsetup.cc: Added a "quiet" flag.
+
+	* commands/vpopbull.cc: Added a "quiet" flag.
+
+	* commands/vpasswds.cc: Added a "quiet" flag.
+
+	* commands/vpasswd2cdb.cc: Added a "quiet" flag.
+
+	* commands/vpasswd.cc: Added a "quiet" flag.
+
+	* commands/vdeluser.cc: Added a "quiet" flag.
+
+	* commands/vaddusers.cc: Added a "quiet" flag.
+
+	* commands/vdeliver.cc: Added a "quiet" flag.
+
+	* commands/vchforwards.cc: Added a "quiet" flag.
+
+	* commands/vchattr.cc: Added a "quiet" flag.
+
+	* commands/listvdomain.cc: Added a "quiet" flag.
+
+	* commands/vadduser.cc: Added a "quiet" flag.
+
+	* authenticate/authvlib.cc (check): make the virtual / non-virtual
+	decision here rather than in authenticate, in order to handle
+	"baseuser-virtuser" type usernames.  This fixes the Courier-IMAP
+	auth module problems.
+
+2000-04-06  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* doc/FAQ.texi (Upgrading from Previous Versions): Added this
+	section to answer questions regarding what needs to be done to
+	upgrade to the current version.
+
+2000-04-05  Bruce Guenter  <bguenter@daedalus.bfsmedia.com>
+
+	* Released version 0.96.3
+
+2000-04-04  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* doc/vmailmgr-cgi.texi (Top): Expanded the "vadduser" section to
+	explain the new optional "userdir" field.
+
+	* cgi/vadduser.cc (CGI_MAIN ): Modified to use the new adduser2
+	interface.
+
+	* cgi/vaddalias.cc (CGI_MAIN ): Modified to use the new adduser2
+	interface.
+
+	* daemon/dispatch.cc: Removed dispatch entries for adduser,
+	addalias, and addaliasp.
+
+	* daemon/adduser2.cc (CMD): Added this new command, which combines
+	the functionality of adduser, addalias, and addaliasp.
+
+	* daemon/addaliasp.cc (CMD): Modified to use build_forwards.
+
+	* daemon/addalias.cc (CMD): Modified to use build_forwards.
+
+	* daemon/adduser.cc (CMD): Only add non-empty forwarding addresses.
+	(build_forwards): Moved the forward-list building code common to
+	adduser, addalias, and addaliasp into this routine.
+
+	* daemon/main.cc (handle_connection): Log command response before
+	attempting to send data back to client.
+	(abortreq): Log abort code before closing FD.
+	(decode_data): Removed the test to check for empty parameters,
+	since some of the modules expect this possibility.
+
+2000-04-03  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* authenticate/vauthenticate.cc (getdata): Buffer doesn't need to
+	be static.
+
+	* authenticate/checkvpw.cc (getdata): buffer doesn't need to be
+	static.
+
+	* lib/vpw/vpwtable.h (class vpwtable): Moved the vpwtable class
+	definition into this file.
+
+2000-04-01  Bruce Guenter  <bruceg@daedalus.bfsmedia.com>
+
+	* Released version 0.96.2
+	
+	* daemon/state.cc: Since the daemon always forks, remove all of
+	the uid/gid saved state, and never restore it.  This class should
+	be renamed, since it does not really "save" any significant state.
+
+	* commands/vaddalias: Fixed quoting bug in this script.
+
+2000-03-21  Bruce Guenter  <bruceg@daedalus.bfsmedia.com>
+
+	* authenticate/vauthenticate.cc (main): Authenticate as virtual
+	only, and print out the user data if authentication succeeds.
+
+	* authenticate/authvlib.cc (authenticate): Fixed typo declaring
+	"baseuser" twice, preventing authentication from working.
+
+2000-03-07  Bruce Guenter  <bruceg@daedalus.bfsmedia.com>
+
+	* authenticate/vauthenticate.cc: Added this simple module that
+	accepts domain name, user name, and pass phrase on stdin, and
+	exits successfully if they can be authenticated.
+
+2000-02-12  Bruce Guenter  <bruceg@daedalus.bfsmedia.com>
+
+	* commands/vaddalias: Made this mini-program into a shell script.
+
+	* daemon/chattr.cc (CMD): Translate multiple values into a single
+	NUL-delimited list.
+
+	* commands/vsetup.cc (cli_main): Added error messages if execution
+	of vsetup-pre or vsetup-post fails.
+
+	* Removed old php3 support and placed Mike Bell's PHP3 code in.
+
+	* Applied patches by Mike Bell to allow vsetup to run a command
+	before and after executing.
+
+2000-02-03  Bruce Guenter  <bruceg@daedalus.bfsmedia.com>
+
+	* doc/FAQ.texi: Fixed typo reversing virtuser and baseuser.
+
+2000-01-12  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* authenticate/authvmailmgr.cc: Completed initial coding of this
+	module, still needs testing.
+
+	* authenticate/checkvpw.cc (fail): Removed unused string "r".
+
+2000-01-05  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* authenticate/authvmailmgr.cc: Started authentication module for
+	Courier IMAP.
+
+	* authenticate/authvlib.cc: Moved some of the functions out of
+	checkvpw.cc and generalized them here.
+
+	* authenticate: Moved checkvpw directory here.
+
+1999-10-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* checkvpw/checkvpw.cc (authenticate): Changed logic here to
+	assume a missing entry in both locals and virtualdomains is
+	intended to be local.
+
+1999-10-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/*.cc: Modified to use new validate_forward.
+
+	* lib/misc/vdomain_chattr.cc (chdest): Modified to use new
+	validate_forward.
+
+	* lib/misc/vdomain_validate.cc (validate_forward): Renamed
+	validate_redirect to this, and removed the handling for a
+	comma-seperated list of addresses.
+
+	* commands/vchforwards.cc (cli_main): Added code to validate the
+	forwarding addresses.
+
+	* commands/vadduser.cc (make_user): Validate the forwarding
+	addresses before creating the user.
+
+1999-10-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/chattr.cc (CMD): Changed call to strtol to strtoul.
+
+	* lib/config/read_uns.cc (read_uns): Modified this routine to
+	treat all negative numbers as -1, and changed the call from strtol
+	to strtoul.
+
+1999-10-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/FAQ.texi: Updated the answers and added information about
+	how mail gets delivered.
+
+	* lib/misc/vdomain_add.cc: Removed both vdomain::addalias and
+	vdomain::adduser.
+
+	* commands/vsetup.cc (setup_alias): Removed the use of
+	vdomain::addalias.
+
+	* commands/vadduser.cc (add_alias): Removed the use of
+	vdomain::addalias.
+
+	* commands/vaddusers.cc (add_one): Removed the use of
+	vdomain::adduser and vdomain::addalias.
+
+1999-10-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.96.1
+
+	* doc/vmailmgr-cgi.texi: Updated listvdomain documentation.
+
+	* cgi/listvdomain.cc (show_user): Merged show_mbox and show_alias
+	into this one routine.
+	(load_users): Fixed length of incoming code.
+	(show_user): Changed formatting of aliases.
+
+1999-10-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/listvdomain.cc: Recoded to use modified listdomain protocol
+	interface.
+
+	* lib/misc/vdomain_add.cc (addalias, adduser): Call set_defaults
+	on new vpwentry.
+
+	* lib/misc/vpwentry_from_old.cc (from_old_record): Call
+	set_defaults on resulting vpwentry.
+
+	* commands/vadduser.cc (make_user): Call set_defaults on new
+	vpwentry.
+
+	* daemon/lookup.cc (lookup_and_validate): Call set_defaults on new
+	vpwentry.
+
+	* lib/misc/vpwentry.cc: Moved vpwentry::set_defaults into its own
+	module, and removed the call to set_defaults from the constructors.
+
+	* lib/misc/vpwentry_from.cc: Made the from_old_record and
+	from_ver1_record public, and moved them into their own modules.
+
+	* daemon/listdomain.cc (CMD_FD): Changed the protocol to strip the
+	count from the initial message, to output each entry as a seperate
+	response (with length and all), and to include full vpwentry
+	details in each entry rather than requiring seperate lookups.
+
+1999-09-30  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.96
+	
+	* checkvpw/checkvpw.cc (main): Removed extraneous ; causing bug.
+
+	* lib/misc/exec.cc (execute): Skip over directories with identical
+	parents, to prevent double execution.
+
+	* checkvpw/checkvpw.cc (check): Fixed inverted "nodefault" flag to
+	domain->lookup.
+
+	* lib/misc/vpwentry_from.cc (from_record): Turned the if/else
+	block into a switch statement.
+
+	* commands/vadduser.cc (set_defaults): Turn off creation of a
+	mailbox if the base command name is "vaddalias".
+	Also, use argv0base instead of "vadduser" for the command name.
+
+	* lib/misc/vpwentry_from.cc (from_ver1_record): Fixed bug in
+	importing version 1 records.
+
+	* commands/vdeliver.cc (dump): The input needs to be rewound here
+	the second time through, so rewind it always.
+
+1999-09-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/listvdomain.cc (cli_main): Print out a banner before
+	the listing.
+
+1999-09-27  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/configuration.texi: Updated the configuration documentation
+	to match current implementation aspects.
+
+	* lib/misc/exec.cc (execute): Changed behavior of execute to
+	execute the global before the local directories, and to abort on
+	any error, but translate 99 to 0 (no error).
+
+1999-09-23  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/vaddalias.cc (CGI_MAIN ): Adjusted for changed parameter
+	ordering.
+
+	* daemon/log.cc: Added several password-obscuring constants,
+	rather than repeating them in each command.
+
+	* daemon/lookup.cc (CMD): Changed format of result.
+
+	* daemon/check.cc (CMD): Changed format of result to seperate
+	parts with a NUL.
+
+	* daemon/addalias.cc (CMD): Now takes multiple destinations.
+
+	* daemon/addaliasp.cc (CMD): Changed order of parameters to allow
+	for multiple destination parameters.
+
+	* daemon/log.cc (logcommand): Removed all varieties of this
+	function except the one that takes a single "command" argument.
+
+	* daemon/adduser.cc (CMD): Added handling for a list of forwards.
+
+	* daemon/dispatch.cc (dispatch_cmd): Changed handling of commands:
+	there is now a minimum and a maximum number of arguments, and the
+	"decode_virtual" is a manditory -- if set, the "baseuser-virtual"
+	format is not allowed.  This means all the server commands now
+	require seperate domain name and virtual user name arguments (all
+	the CGIs do this anyways).
+
+	* daemon/check.cc (CMD): Added handling for mailbox and multiple
+	forwards of virtual users.
+
+	* daemon/dispatch.cc: Added check back into the list of commands.
+
+	* cgi/vcommand.py (main): Adapted to new interface.
+
+	* cgi/vmailmgr.py: Revised the interface to be somewhat more
+	object based, and tested minimally.
+
+1999-09-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/listvdomain.cc (setup_format): Added handling for cell and
+	title prefix and suffix strings, as well as cell, paragraph, and
+	table alignment.
+
+1999-09-20  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/vmailmgr.py: Split off most of the generic functionality
+	from vcommand.py into this module, completed base CGI
+	functionality.
+
+1999-09-19  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/vcommand.py: Started this generic Python vmailmgr command
+	CGI.
+
+1999-09-16  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeliver.cc (cli_main): Adapted to the new execution
+	framework.
+
+	* checkvpw/checkvpw.cc (check): Adapted to the new execution
+	framework.
+
+	* lib/misc/exec.cc (execute): Removed the old "exec" framework in
+	favour of this function, which traverses through the configuration
+	directories and tries to execute the named file.
+
+	* doc/vadduser.pod: Updated this documentation.
+
+	* commands/vadduser.cc: Added an option to not create a mailbox
+	for this user, allowing this program to be used in place of
+	vaddalias.
+	(add_user): Modified logic to optionally ask for a password.
+
+	* commands/vconf2dir: Fixed quoting when creating the new config
+	files, and removed the "set -x" flag at the top.
+
+	* commands/vchforwards.cc (cli_main): Adapted this program from
+	vchalias, and removed vchalias from the distribution.
+
+	* commands/vchattr.cc: Wrote this command to change a virtual
+	user or users' attributes.
+
+1999-09-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* checkvpw/checkvpw.cc: Login failures cause execution of
+	"config/checkvpw-loginfail", and other failures cause execution of
+	"config/checkvpw-error", both with an error message in
+	$CHECKVPW_ERROR.
+
+	* commands/vdeliver.cc (deliver_partial): Rewrote loop so that
+	looping will always sleep.  If the file creation failed, it would
+	previously loop immediately.
+
+1999-09-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/FAQ.texi: Replaced references to vmailmgr.conf with
+	vmailmgr/
+
+1999-09-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/vpopbull.pod: Wrote a man page for vpopbull.
+
+1999-09-10  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vpwentry_auth.cc (authenticate): Wrote this new
+	routine, to replace the use of crypt_cmp when authenticating
+	virtual users.
+
+	* lib/misc/pwentry_auth.cc (authenticate): Wrote this new routine,
+	to replace the use of crypt_cmp when authenticating users.
+
+1999-09-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/listvdomain.cc: Added options to list only users, only
+	aliases, or selected names listed on the command line.
+
+	* lib/misc/vpwentry_from.cc (from_ver1_record): Fixed off-by-one
+	bug.
+
+	* lib/misc/vpwentry_to.cc (to_record): Fixed problem in creating
+	records without any forwarding addresses.
+
+	* commands/vadduser.cc: Commented out extra-data handling.
+
+	* lib/misc/exec.cc (setenv): Commented out
+
+	* lib/misc/vpwentry.h (struct vpwentry ): Commented out the extra
+	data string.
+
+	* cgi/vchattr.cc (CGI_MAIN ): Wrote this simple modification to
+	vchalias, which can change any attribute.
+
+	* daemon/chattr.cc (CMD): Convert the attr string to an integer
+	before running domain.chattr.
+
+	* lib/misc/vdomain_chattr.cc (chattr): Added attribute handlers
+	for message size/count and account expiry.
+
+	* lib/misc/vdomain.h (class vdomain): Changed attribute name
+	constants from strings to integers.
+
+1999-08-23  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/configuration.texi (Search Order): Corrected a typo: the
+	local directory is named ".vmailmgr", not "vmailmgr".
+
+1999-08-21  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vadduser.cc: Added hard/soft quota options, and a
+	password option for vaddalias.
+
+	* lib/misc/vpwentry.h (struct vpwentry ): Added hard/soft quota
+	values.
+
+1999-08-18  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vpasswd.cc (cli_main): Modified to call
+	vdomain::chattr.
+
+	* commands/vpasswds.cc (change_one): Modified to call
+	vdomain::chattr.
+
+	* cgi/vchalias.cc (CGI_MAIN ): Use ATTR_DEST instead of a
+	hard-coded string.
+
+	* cgi/vpasswd.cc (CGI_MAIN ): Use ATTR_PASS instead of a
+	hard-coded string.
+
+	* daemon/chattr.cc (CMD): Modified to call vdomain::chattr.
+
+1999-08-16  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vdomain_chattr.cc (chattr): Created this new routine to
+	generalize attribute modification.
+
+1999-08-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/exec.cc (exec_list): Takes a strlist parameter instead
+	of a string.
+
+	* lib/misc/strlist.h (class strlist ): Removed the NUL constant.
+
+	* lib/misc/vpwentry.h (struct vpwentry ): Removed the NUL constant
+	in favour of the new one in mystring.
+
+	* lib/config/read_list.cc (read_list): Adapted to use
+	strlist::read instead of a custom list reading function.
+
+1999-08-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/strlist.h (class keystrlist): Split off the
+	functionality to handle keyed strings ("key=value" format) into a
+	seperate class.
+
+	* lib/misc/vpwentry.h (struct vpwentry ): Adapted to using strlist
+	functions.
+
+	* lib/misc/strlist.h (class strlist ): Moved the string list
+	management into its own class.
+
+	* commands/vquota.cc: Started writing this quota management
+	utility.
+
+	* commands/vdeliver.cc (cli_main): Fixed invocation of exec*
+	functions.
+
+	* commands/vadduser.cc: Added code to set the default values of
+	the new data items, and to set them when creating the user.
+
+	* checkvpw/checkvpw.cc (main): Fixed invocation of exec*
+	functions.
+
+1999-08-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/configuration.texi: Did some minor re-organization, and
+	added a higher level note regarding environment variables and
+	return codes for executed programs.
+
+1999-08-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/exec.cc (setenv): Set environment variables for quota,
+	message size, message count, creation time, expiry time, personal
+	data, and all the extra data.
+	(exec_list): Changed interface to all the exec_* routines: the
+	error message string is passed as a parameter, and the return
+	value is the error return code or zero.
+
+	* lib/misc/vpwentry_from.cc (from_uint): Modified to accept "-*"
+	as the negative pattern.
+
+	* lib/misc/utoa.cc (utoa): Moved this routine into its own module.
+
+1999-08-10  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/vpasswd.cc (CGI_MAIN ): Modified to call "chattr".
+
+	* cgi/vchalias.cc (CGI_MAIN ): Modified to call "chattr".
+
+	* daemon/dispatch.cc: Removed entries for chpass, chalias, and
+	delalias.
+
+	* daemon/chattr.cc (CMD): Merged the functions of chalias and
+	chpass into this new command.
+
+	* lib/misc/vdomain.h (class vdomain): Removed delalias command.
+
+	* lib/misc/vdomain_deluser.cc (deluser): Removed mailbox test to
+	see if the named entry was a "user".
+
+	* commands/vdeliver.cc (inject): Handle failure properly here.
+
+1999-08-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeliver.cc (deliver_partial): Rewrote the delivery
+	mechanism to do partial file delivery.
+	(write_envelope): Rewrote the envelope handling code to use
+	mystring_iter (big simplification).
+
+	* commands/vconf2dir: Fixed non-portable increment statement.
+
+	* commands/vadduser.cc: Added options for the extra virtual user
+	data, but not the code to handle the options.
+
+1999-08-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vpasswd2cdb.cc (getpw): Call vpwentry::from_record,
+	since the original text file format is compatible with its import
+	routine.
+
+	* lib/misc/vdomain_validate.cc (validate_redirect): Call exists
+	instead of lookup.
+
+	* lib/misc/vdomain_lookup.cc (exists): Wrote this routine to test
+	if a name exists in a virtual domain.
+
+	* lib/misc/vpwtable_exists.cc (exists): Added this routine to do a
+	simple check if a user exists, without doing any format
+	translations.
+
+	* lib/misc/vpwentry.h (class vpwtable): Turned the "cdb" pointer
+	into a void pointer to allow for easier extension to non-CDB
+	formats.
+
+	* lib/config/*: Added new default configuration items for the
+	quota and expiry items.
+
+	* lib/misc/vdomain_*.cc: Adpoted to the new vpwentry conventions.
+
+	* lib/misc/exec.cc (setenv): Always set MAILDIR to vpw->mailbox,
+	which will be empty for an alias user.
+
+	* lib/misc/vpwentry.cc (set_defaults): Added this new routine to
+	set the defaults on a vpwentry from the current configuration.
+
+	* lib/misc/vpwentry_from.cc (from_record): Moved this routine into
+	its own module, and added parsing for the new fields.
+
+	* lib/misc/vpwentry_to.cc (to_record): Moved this routine into its
+	own module.
+
+	* lib/misc/vpwentry.h (struct vpwentry ): Added new fixed fields
+	to the structure: personal, quota, msgsize, msgcount, ctime, and
+	expiry.
+
+1999-08-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vpwentry_getset.cc (get): Added this routine to get the
+	value of a data variable.
+	(set): Added this routine to add a variable to the data set,
+	replacing its value if it already exists.
+
+	* lib/misc/vpwentry.cc (to_record): Rewrote this routine to output
+	the new "version 1" record format.
+
+	* lib/misc/vpwentry.h (struct vpwentry ): Expanded this structure,
+	replacing the "dest" field with "mailbox" and "forwards" items,
+	and added a "datastr" field.
+	
+	* lib/misc/vpwentry.cc (from_old_record): Adapted this code from
+	the old vpwentry::from_record routine.
+
+	* Released version 0.95
+
+1999-08-06  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vpopbull.cc (scan_bulletins): Modified the logic here
+	to not fail if one of the bulletin scans fails.
+
+	* commands/vdeliver.cc (inject): Fixed missing argv[0] in call to
+	execl here.
+
+1999-08-05  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vpopbull.cc: Moved this program into the commands
+	directory.
+	(scan_bulletins): Added specific information to error messages.
+
+	* lib/misc/exec.cc (setenv): Moved the common code to set up the
+	environment for virtual users into a common routine here from
+	checkvpw.cc and vdeliver.cc.
+
+1999-08-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/configuration.texi: Added sections for the new execution
+	hooks.
+
+	* checkvpw/checkvpw.cc (check): Fixed this to set the VUSER
+	environment variable immediately after looking up the base user.
+
+1999-08-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* checkvpw/checkvpw.cc (main): Modified to execute the contents of
+	checkvpw-postexec.
+
+	* lib/config/showvconfig.cc.in: Built this new program template to
+	show the config parameters.
+
+	* commands/vdeliver.cc (cli_main): Make vdeliver execute a list of
+	commands before and after doing the delivery.  Will set $MAILDIR
+	and $VUSER.
+
+	* checkvpw/vpopbull.cc: Moved bulletins.cc into this file, built a
+	main routine, and added error logging.
+
+	* lib/misc/exec.cc (exec_list): Created this routine to execute a
+	list of commands, returning the first error as a string.
+	(exec_one): Created this routine to shell and execute a single
+	command using "/bin/sh -c '<command>'".
+
+	* checkvpw/checkvpw.cc: Added a hook to execute a list of programs
+	before and after running setuid.  The "before" programs are read
+	from the global config to avoid security holes.  $HOME and $USER
+	are set for both, and $MAILDIR and $VUSER are set for the "after"
+	programs.
+
+1999-08-02  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.94
+
+	* daemon/dispatch.cc: Commented out the "stat" and "statall"
+	commands, that no longer do anything useful (the forking daemon
+	causes the statistics to be meaningless).  Also removed the code
+	in "dispatch" to count invocations of a particular method.
+
+	* daemon/lookup.cc (lookup_and_validate): Fixed a false negation
+	in the logic when checking for an existing virtual user.
+
+	* lib/misc/maildir.cc (mkdirp): Fixed off-by-one bug in recursive
+	case.
+
+	* commands/vdeliver.cc: Fixed bug caused by assigning from an int
+	to a bool through a pointer (since bools are only a single byte).
+
+	* checkvpw/checkvpw.cc: Rewrote this code to do the password
+	checking directly without calling up to the daemon.
+
+	* daemon: moved lookup_baseuser into lib/misc, removed the call to
+	setup a saved_state from it, and adjusted all the calls to
+	lookup_baseuser in the daemon to fit.
+
+1999-07-30  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeliver.cc: Moved this program from clients into
+	commands, and made it work the the CLI library.
+	(cli_main): Does a call to domain.lookup now instead of a server
+	call.
+	(read_me): Rewrote to use config->qmail_root() instead of a
+	hard-coded /var/qmail.  This is the last place (verified with
+	grep) that has a hard-coded /var/qmail.
+
+1999-07-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/config/config_read.cc (config_read): Fixed a typo: I had
+	typed '=' instead of '+' to create the full name.
+
+1999-07-27  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/chpass.cc (CMD): Calls the vdomain::chpass routine
+	instead of doing it by hand through the vpwtable code.
+
+	* commands/vpasswd2cdb.cc (cli_main): Removed an extraneous call
+	to end_getpw.
+
+	* lib/misc/vpwentry.h (class vpwtable): Added this new
+	abstraction, a virtual password table, that contains all the
+	low-level table manipulation routines.  All other code has been
+	adjusted to fit this model.
+
+1999-07-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/lookup_domain.cc: Moved is_local and find_virtual into
+	this file from daemon/lookup.cc.
+
+	* daemon/lookup.cc (CMD): Converted to using vdomain::lookup.
+
+	* daemon/check.cc (CMD): Converted to using vdomain::lookup.
+
+	* lib/misc/vdomain_lookup.cc (lookup): Moved the daemon function
+	lookup_virtuser into this method.
+
+	* Inserted the latest cli library and adapted all the command line
+	programs to handle the changes.
+	
+	* Inserted the latest mystring class and adapted all the code to
+	handle it.
+
+	* Rewrote the virtual user manipulation code from lib/misc/vuser*,
+	and moved it all into the vdomain class (was struct).  Adjusted
+	all other references to use this new code.
+
+1999-07-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.93
+
+	* daemon/adduser.cc (CMD): Prefix the user dir destination with
+	"./".
+
+	* lib/misc/vuser_set.cc (vuser_set): Allow leading '/' in
+	destination string, in addition to leading '.' and '&'.
+
+1999-07-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vsetup.cc (setup_passwd): Modified to use the new
+	string iterator class.
+
+	* lib/misc/stringiter.h (class mystring_iter): Wrote this class to
+	provide an iterator over a newline (or NUL, even) seperated list
+	within a string.
+
+1999-07-20  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vsetup.cc (setup_passwd): Changed the alias seperator
+	character from ',' to '\n'.
+
+	* lib/config/read_list.cc (read_list): Wrote this routine to read
+	a config item containing a list of values.
+
+	* lib/config/config_readlist.cc (config_readlist): Wrote this new
+	routine to read a list of values from a file, newline seperated.
+
+1999-07-19  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/configuration.texi: Wrote this new document describing the
+	new configuration structure, adapted from the now obsolete
+	vmailmgr.conf.sample.
+
+1999-07-18  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/config/read_*.cc: Moved the overhead for maintaining the
+	cache into these read functions instead of duplicating it in each
+	config variable function.
+
+	* lib/config/build-config.sh: Create a cache for each config
+	variable in order to eliminate duplicate readings of a single
+	variable.
+
+	* daemon/pwentry_table.cc (operator[]): Replaced the previous
+	implementation (a cache) with one that just calls getpwnam.  This
+	avoids creating extra dynamic data in the form of many pwentry
+	structures.
+
+	* daemon/lookup.cc (lookup_baseuser): Removed an extraneous
+	re-creation of the pwentry returned from the pwentry_table.
+
+	* lib/config/read_*.cc: Removed the translation from '_' to '-'
+	for filenames from the code and moved it into the build-config.sh
+	script.  This moves the constant conversion from run-time to
+	build-time.
+
+	* lib/config/configrc.cc (configuration): Made the constructor
+	take a pointer instead of a reference, which was probably the
+	saner thing to do from the start.
+
+	* lib/config/read_dir.cc (read_dir): Modified the logic here so
+	that the macros for creating the config reading routines can be
+	completely uniform.
+
+	* daemon/state.cc (saved_state): Since the saved state is never
+	un-saved, don't try to establish what the previous state is with
+	getuid and getegid.
+
+	* daemon/state.h: Turned the CHANGE_STATE macro into a no-op,
+	since the state is already saved when doing any lookup.
+
+	* daemon/lookup.cc (lookup_baseuser): Set up the saved state
+	immediately upon successfully doing a base user lookup.
+
+	* daemon/state.h (class saved_state): Removed the pwentry pointer
+	and made the domain a non-pointer as well.
+
+1999-07-17  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/state.cc: Modified these routines to set up a pwentry
+	before setting up the vdomain, as well as properly restoring the
+	old config pointer.
+
+	* commands/*.cc: Replaced all instances of "domain->" with
+	"domain.", since "domain" is no longer a pointer.
+
+	* clients/vdeliver.cc (main): Modified to set up a pwentry before
+	setting up the vdomain.
+
+	* clients/checkvpw.cc (set_user): Modified to set up a pwentry
+	before setting up the vdomain.
+
+	* commands/vcommand.cc (go_home): Modified to create a global
+	pwentry named "user", and build the domain and config based on
+	that.
+
+	* lib/misc/vdomain.cc (vdomain): Modified the constructors to take
+	a pwentry parameter to build the domain config from.
+
+	* lib/misc/pwentry.cc: Moved this file here from daemon, added a
+	"config" structure entry, and added a default constructor.
+	(pwfile): Removed the pwfile_cache member, which was a kluge for
+	what I thought was a bug somewhere else.
+
+1999-07-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Forwarded-ported envelope delivery re-write from 0.92.2 for
+	clients/vdeliver.cc.
+
+1999-07-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/lookup.cc: Converted is_local and find_virtual to use the
+	qmail_root config item.
+
+	* Forwarded-ported logic fix from 0.92.1 for clients/vdeliver.cc.
+
+	* clients/vdeliver.cc (inject): Use the new qmail_root config item
+	to locate the qmail-queue binary.
+
+1999-06-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/hash_table.h: Fixed a typo in the hash table prime list
+	(the last numbers were truncated).
+
+1999-06-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/FAQ.texi: Added a "troubleshooting" section, to be filled in
+	as questions arrive.
+
+1999-06-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Modified all the sources to use the new configuration class
+	members.
+
+	* commands/vcommand.cc (go_home): Initialize the password_file
+	global from config->password_file() here.
+
+	* lib/config/configrc.cc: Totally re-wrote the configuration
+	system to use a subdirectory style config, with individual files
+	containing the configuration values on their first line.  The
+	configuration modules are also built by a script, and broken down
+	into individual object modules to reduce the size of programs that
+	don't use all the options.
+
+1999-06-05  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/*.cc: Moved the calls to CHANGE_STATE to immediately
+	after validating the user, to allow the config set up by the
+	saved_state to be used immediately.
+
+	* clients/checkvpw.cc (set_user): Set up a vdomain here and set
+	the config to allow for locally-configured bulletin directories.
+	(main): Moved the call to set_user higher, to allow the config to
+	be used earlier to set the error maildir.
+
+	* clients/vdeliver.cc (main): Set up a vdomain and set the config
+	to its config, to load a local configuration when doing
+	deliveries.
+
+	* daemon/pwentry.cc: Removed the definitions for user_dir_rel and
+	user_dir_abs, since vdomain::userdir will do the job now (it seems
+	that user_dir_abs wasn't even used, too).
+
+	* daemon/state.cc: Moved the constructor and desctuctor for
+	saved_state into this object, and added a call to push a new
+	configuration if state was changed successfully.
+
+	* commands/vcommand.cc: Moved the go_home routine into here, and
+	added a global "domain" pointer that will point to the current
+	virtual domain.
+	(go_home): Push the domain config onto the config stack.  Now all
+	the command programs will use a local configuration.  This routine
+	will eventually be rewritten to handle multiple domains in the
+	same user.
+
+	* commands/vadduser.cc: Converted to using a vdomain object.
+
+	* Converted all instances of "config." to "config->" where
+	appropriate (the vdomain class has a non-pointer config member, so
+	it doesn't count).
+
+	* lib/misc/server.cc: Rewrote call and connect to take as a
+	parameter the socket filename to use.  server_call::call has a
+	default argument now of config->socket_file to prevent having to
+	change any code, but this might disappear, too.
+
+	* lib/misc/configrc.cc: Turned the global 'config' item into a
+	pointer, to allow other code to essentially push down local
+	configurations onto it.  Wrote config_push and config_pop to
+	assist with this.
+
+	* commands/vaddusers.cc (add_one): Make the alias name lower case
+	before using it, call vuser_adduser with the maildir argument set.
+
+	* lib/misc/vuser_add.cc (vuser_adduser): Modified this routine to
+	remove the call to userdir, forcing the maildir name to be created
+	at a higher level.
+
+1999-06-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/configrc.cc (configuration): Eliminated the #defined
+	default constants, as they are used only once, and moved them
+	directly into the default configuration constructor.
+
+	* lib/misc/configrc.h (class configuration ): Added a "parent"
+	member item that points to the object from which the defaults for
+	this configuration was set (set to NULL in the default object).
+
+	* lib/misc/vdomain.cc: Created this construct to represent a
+	virtual domain.  Copied the functionality from userdir.cc into
+	here (with the plan of removing userdir.cc in the future).  This
+	will become the status-holder for multiple domains within a single
+	real user.
+
+	* lib/misc/configrc.cc (configuration): Added a new constructor
+	that copies the values from a set of defaults and reads in a
+	config file to override those defaults.  To be used for local
+	configuration handling.  Relegated the default constructor to only
+	setting the default values, and added a new global const object
+	config_defaults to hold these.
+
+	* commands/*: Added a call to go_home in every cli_main.
+
+	* commands/go_home.cc (go_home): Wrote this routine to chdir to
+	the user's HOME directory.
+
+1999-06-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/listvdomain.cc (cli_main): I forgot to check the return
+	value of start_getpw here, leading to a core dump when the
+	password table can't be opened.  Fixed.
+
+1999-06-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vsetup.cc (setup_qmail_default): Changed the mode of
+	the created .qmail-default file to 0444 (minus umask) instead of
+	0666 to prevent qmail from complaining on systems where umask
+	defaults to 002 instead of 022, and to prevent inadvertent editing
+	of the .qmail-default file.
+
+1999-05-30  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.92
+
+1999-05-28  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/vdeliver.cc: Rewrote the alias delivery routines to send
+	the email to qmail-queue instead of qmail-inject, since
+	qmail-inject will attempt to reformat the message.
+
+1999-05-27  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/check.cc (CMD): Added a check to ensure that checking the
+	password for an alias fails.
+
+	* doc/*: Changed references from qcc.sk.ca to em.ca.
+
+1999-05-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/addaliasp.cc (CMD): Added this new command to add an
+	alias with a password.
+
+	* doc/vmailmgr-cgi.texi: Updated the documentation for vaddalias.
+	Changed all instances of "necessary" to "required".
+
+	* cgi/vaddalias.cc (CGI_MAIN ): Now allows for an optional new
+	password field pair, and calls addaliasp if they are not empty.
+
+	* lib/misc/server.cc (server_call): Added a new server_call for 5
+	parameters.
+
+	* daemon/log.cc (logcommand): Added a new logcommand routine to
+	handle 5 parameters.
+
+	* daemon/dispatch.cc: Modified the dispatch entry for addalias.
+
+	* daemon/chpass.cc (CMD): Removed the custom password checking
+	since it is now merged into lookup_and_validate.
+
+	* daemon/chalias.cc (CMD): Call lookup_and_validate with the
+	"userpass" flag set to true to allow owners of virtual aliases set
+	up with a password to change their alias.
+
+	* daemon/lookup.cc (lookup_and_validate): Modified to optionally
+	do comparisons against the virtual user's password if the
+	comparison against the administrator's password fails.  Removed
+	the allowance for empty passwords.  Made all the password
+	mis-match messages the same.  The admin password check is done
+	before the virtual user check to avoid giving away information
+	about virtual users.
+
+	* commands/vaddalias.cc (cli_main): Set passwords on aliases by
+	passing in a '-p' or '--password' flag.
+
+	* lib/misc/vuser_add.cc (vuser_addalias): Modified to allow
+	passwords on aliases.
+
+1999-05-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.91
+
+1999-05-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/chalias.cc (CMD): Bug fix: was passing "false" for
+	"mustexist" to lookup_and_validate, when it should have been
+	"true".
+
+	* commands/vdelalias.cc, commands/vdeluser.cc,
+	commands/vaddusers.cc, commands/vaddalias.cc,
+	commands/vpasswds.cc, commands/vchalias.cc: Added a mechanism to
+	count and report the number of errors encountered.
+
+	* doc/vmailmgr-cgi.texi: Added a chapter for the chalias command.
+	Also added sections for vdelalias and vdeluser, as well as sorting
+	the sections into alphabetical order.
+
+	* cgi/vchalias.cc: Wrote the CGI program to call the chalias
+	command.
+
+	* doc/vchalias.pod: Wrote the documentation page for the vchalias
+	command.
+
+1999-05-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/configrc.cc (DEFAULT_DEFAULT_USERNAME): Changed the
+	default default username from '*' to '+', to avoid shell
+	screwups.  Updated documentation.
+
+1999-05-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/checkvpw.pod: Fixed filename glitch -- replaced all
+	instances of virtualhosts with virtualdomains.
+
+1999-05-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vpwentry_putpw.cc (putpw): Changed logic of "onlyadd"
+	parameter.  If set, will fail if the name already existed.  If not
+	set, will fail if the name did not already exist.
+
+	* daemon/dispatch.cc: Added a dispatch entry for chalias.
+
+	* daemon/chalias.cc (CMD): Created this server command to change
+	an existing alias to a new destination, using the new vuser_set.
+
+	* daemon/adduser.cc (CMD): Changed to use vuser_set.
+
+	* daemon/addalias.cc (CMD): Changed to use vuser_set.
+
+	* lib/misc/vuser_add.cc: Changed to use vuser_set.
+
+	* commands/vadduser.cc (add_user): Changed to use vuser_set.
+
+	* lib/misc/vuser_set.cc (vuser_set): Renamed vuser_add to
+	vuser_set, and moved it into this file.  vuser_set can be used to
+	change existing entries as well as to add new entries.
+
+	* commands/vrehash.cc (lock_dir): Set permissions on created CDB
+	file to 0600.
+
+	* commands/vpasswd2cdb.cc (cli_main): Set permissions on created
+	CDB file to 0600.
+
+	* lib/misc/vpwentry_putpw.cc (putpw): Set permissions on created
+	CDB file to 0600.
+
+	* lib/misc/vpwentry_delpw.cc (delpw): Set permissions on created
+	CDB file to 0600.
+
+	* clients/vdeliver.cc: Changed all I/O to use fdbuf primitives.
+	(deliver): Changed permissions on created file to 0666 to 0600
+	(mail should be private).
+
+1999-04-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.90.2
+
+1999-04-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/userdir.cc (userdir): Use the multiple-argument
+	mystring constructor to make pasting the slices together more
+	efficient.
+
+	* daemon/main.cc: Added include of <stdio.h> to pull in perror
+	properly.
+
+1999-04-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.90.1
+
+1999-04-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vpwentry_putpw.cc: Removed include of errnos.h
+
+	* lib/misc/md5-crypt.c: Added definitions for MIN and MAX if they
+	aren't defined.
+
+1999-04-05  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/vmailmgr.conf.sample: Removed the entry for
+	cdb-password-file, as that variable is not used.
+
+1999-04-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.90
+
+	* doc/FAQ.texi: Noted that the C++ libraries are no longer
+	needed.
+
+	* clients/bulletins.cc (stat_maildir): Fixed two bugs: timestamp
+	file was named "maildir/cur/.timestamp" instead of just
+	"maildir/.timestamp"; timestamp file was opened for writing
+	without a mode, causing the resulting file to have an
+	indeterminate mode.
+
+	* doc/FAQ.texi: Added an answer regarding IMAP support.
+
+1999-04-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (handle_connection): Only print out the "Accepted
+	connection" message if the verbose flag is set.
+
+1999-04-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/md5-crypt.c (md5_crypt_r): This routine depended on the
+	result of "strncpy" pointing to the end of the destination
+	string.  This is non-standard behavior.  Fixed such that the "cp"
+	pointer tracks its position manually.
+
+	* cgi/listvdomain.cc: Converted to fdbuf.
+
+	* daemon/main.cc (usage): Converted to fdbuf.
+
+	* daemon/log.cc: Converted to fdbuf.
+
+	* daemon/map_table.cc (map_table): Converted to fdbuf.
+
+	* daemon/list_table.cc (list_table): Converted to fdbuf.
+
+	* commands/*: Converted from iostream to fdbuf.
+
+	* lib/cli/main.cc: Use the new "operator<<" methods of fdobuf.
+
+	* lib/misc/validate.cc (validate_redirect): Converted from using
+	ostrstream to mystring for growing error messages.
+
+	* lib/misc/configrc.cc (read_config): Use the new "operator<<"
+	methods of fdobuf for writing messages.
+
+	* lib/misc/passwdfn.cc: Converted to using fdbuf objects.
+
+1999-03-31  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/pwcrypt.cc: Adapted these routines to using the GNU MD5
+	library and the md5_crypt routine.
+	(crypt_cmp): Revised the algorithm here to use the old MD5 routine
+	only for old passcodes, md5_crypt for hashes starting with "$1$",
+	and crypt otherwise.  This should be compatible with all
+	implementations.
+
+	* lib/misc/configrc.cc (read_config): Modified to use fdibuf
+	instead of ifstream.
+	(cmp): Fixed logic to properly parse "STR *= *STR" instead of
+	"STR *(=+ *)+STR".
+
+	* Changed the copying policy to GPL.
+
+1999-03-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.89.1
+
+	* configure.in: Add a --enable-md5 flag to set USE_MD5.
+
+	* lib/misc/pwcrypt.cc: Imported implementation of crypt_cmp and
+	pwcrypt from 0.87, using USE_MD5 as a selector.
+
+1999-03-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.89
+
+	* daemon/main.cc (handle_connection): Move the exit(0) out of the
+	if block so that the child always exits.
+
+	* daemon/fork.cc (do_fork): Bump up the fork counters in the child
+	as well as the parent so that the accounting commands work
+	properly.
+
+	* clients/bulletins.cc (stat_maildir): Fixed type: open the
+	timestamp file for output, not the maildir.
+
+1999-03-20  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/bulletins.cc (stat_maildir): The timestamp on the "cur"
+	directory is unreliable.  Create a zero-length ".timestamp" file
+	and use its modification mode for last-login information.
+
+1999-03-18  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/listdomain.cc (CMD): Fixed a non-incrementing loop
+	counter.
+
+	* daemon/fork.cc (handle_children): Now checks for both pid == -1
+	and pid == 0 to terminate the wait loop.
+
+	* lib/misc/vpwentry_putpw.cc (putpw): If the input file does not
+	exist, skip the loop and add the record to a new output file.
+
+	* lib/cdb++/cdb_reader.cc (cdb_reader): Set the failed flag to the
+	result of opening the file.
+
+	* lib/misc/vpwentry_putpw.cc (putpw): Fixed inverted boolean bug.
+
+	* daemon/lookup.cc (lookup_baseuser): Fixed bug: the pwentry
+	pointer returned by operator[] on the pwentry_table gets deleted
+	when the pwentry_table goes out of scope (and all kinds of weird
+	things happen to the data).
+
+	* daemon/pwentry.cc (pwfile): Cache the value of pwfile for future
+	calls.
+
+	* daemon/lookup.cc (lookup_baseuser): Use "right" instead of the
+	silly pointer increment logic to get the virtual name substring.
+
+1999-03-17  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/dispatch.cc (dispatch_cmd): Remove all fork handling from
+	this routine.
+
+	* daemon/main.cc (handle_connection): Call do_fork immediately
+	after accepting the connection.
+
+1999-03-16  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vsetup.cc (setup_qmail_default): Set the initial value
+	of .qmail-default to "|@BINDIR@/vdeliver".
+
+	* commands/vrehash.cc: Rewrote to use CDB functions.
+
+	* daemon/listdomain.cc (CMD): Send output to 'fd' instead of
+	hard-coded file descriptor 2.
+
+	* daemon/dispatch.cc (dispatch_cmd): Pass the file descriptor to
+	the dispatched function.
+
+	* daemon/main.cc (handle_connection): Modified logic to better
+	suit the always-fork mentality.
+
+	* daemon/dispatch.cc (dispatch_cmd): Changed logic to always
+	fork.
+
+	* At this point, all cache support in vmailmgrd has been removed,
+	and all virtual password table functions will read CDBs.
+
+	* daemon/lookup.cc: Converted the functions here to using the
+	tables instead of the caches.
+
+	* daemon/pwentry_table.cc (pwentry_table): Converted the
+	implementation of pwentry_reader into this class.
+
+	* daemon/hash_table.h (class hash_table): Fixed a long-standing
+	const method issue.
+
+	* daemon/list_table.cc (list_table): Converted the implementation
+	of list_reader into this class.
+
+	* daemon/map_table.cc (map_table): Converted the implementation of
+	map_reader into this class.
+
+	* daemon/listdomain.cc (CMD): Removed the use of the vpwentry
+	cache table.
+
+	* lib/misc/vpwentry_get.cc (rewind_getpw): Wrote this routine to
+	rewind an open cdb table witout re-opening it.
+	(getpw): Converted to using autodelete.
+
+	* daemon/chpass.cc (CMD): Removed the use of the vpwentry cache
+	table.
+
+	* daemon/lookup.cc (lookup_virtuser): Removed the use of the
+	vpwentry cache table.
+
+	* daemon/pwentry.h (struct pwentry): Removed the vpwtable entry.
+
+1999-03-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vpwentry_*.cc: Append ".cdb" to the filename for the
+	CDB file name.
+
+	* lib/misc/configrc.cc: Removed the cdb_password_file entry.
+
+1999-03-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vpwentry_putpw.cc (putpw): Converted to using CDB
+	functions.
+
+	* commands/passwd2cdb.cc (cli_main): Converted to use to_record.
+
+	* lib/misc/vpwentry.cc (to_record): Wrote this one-liner to build
+	a CDB record from the entry.
+
+	* lib/misc/vpwentry_delpw.cc (delpw): Converted to using CDB
+	functions.
+
+	* lib/misc/vpwentry_get.cc (start_getpw): Rewrote to use
+	vpwentry::from_record.
+
+	* lib/misc/vpwentry_getpw.cc (getpw_byname): Rewrote to use
+	vpwentry::from_record.
+
+	* lib/misc/vpwentry.cc (from_record): Wrote this routine to build
+	a vpwentry from a CDB record.
+
+1999-03-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/misc/vpwentry_getpw.cc (getpw_byname): Converted to using
+	CDB functions.
+
+	* lib/misc/vpwentry_get.cc: Converted to using CDB functions.
+
+	* lib/misc/configrc.cc: Added support for configuring the CDB
+	password table name.
+
+	* commands/passwd2cdb.cc: Wrote this program to convert a standard
+	virtual password table into a CDB table.  The initial record
+	format is identical to the old to reduce library conversion
+	issues.
+
+	* lib/misc/vpwentry_get.cc (start_getpw): This routine now returns
+	bool to indicate if the table was opened successfully.
+
+	* Major reorganization of the libraries and header files.  All the
+	libraries are in subdirectories under "lib", and the headers under
+	"include" (with a pile of symlinks).
+
+1999-03-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.88
+
+	* configure.in: Check for libinet and libsocket.
+
+1999-03-10  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/vmailmgr-cgi.texi (Top): Removed warning about passwords
+	being limited to eight characters.
+
+	* commands/vpasswds.cc (change_one): Removed warning about
+	passwords being truncated to eight characters.
+
+	* lib/passwdfn.cc (getpasswd_interactive): Removed warning about
+	passwords being truncated to eight characters.
+	(getpasswd_stdin): Removed another eight character warning.
+
+1999-03-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/pwcrypt.cc: Add a passcode type digit to the MD5 hashes on
+	output, and check for this digit on comparison to determine what
+	type of hashing to use.
+
+1999-03-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/check.cc (CMD): Tidied up result string creation code.
+
+	* lib/vpwentry_getpw.cc (getpw_byname): Copied logic from getpw.
+
+	* lib/vpwentry_get.cc (getpw): Fixed minor logic flaws.
+
+	* lib-dbi/passcode.cc: Added a stub for MD5 authentication.
+
+	* daemon/chpass.cc (CMD): Use renamed pwcrypt.
+
+	* daemon/adduser.cc (CMD): Use renamed pwcrypt.
+
+	* commands/vadduser.cc (add_user): Use renamed pwcrypt.
+
+	* lib/vuser_add.cc (vuser_adduser): Use renamed pwcrypt.
+
+	* lib/vuser_chpass.cc (vuser_chpass): Use renamed pwcrypt.
+
+	* lib/pwcrypt.cc (crypt_cmp): Modified to automatically handle MD5
+	hashed passcodes.
+	Renamed encrypt to pwcrypt, which calls encrypt_md5 to produce MD5
+	hashed passcodes.
+
+	* Completed conversion of source packaging from custom makefiles
+	to automake.
+
+1999-02-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.87
+	
+	* Removed my kludged handling for building shared libraries.  This
+	greatly simplifies the process of moving to both automake and
+	libtool.  The executables are somewhat larger, but still come in
+	under about 25K each (on i386 Linux).
+
+	* clients/bulletins.cc (scan_bulletins): Skip scanning the local
+	bulletin directory if the user is non-virtual.
+
+	* clients/checkvpw.cc (struct user_data): Added a non_virtual flag
+	to this data, indicating that the user is not a virtual user.
+	(main): Pass the non_virtual flag into scan_bulletins.
+
+	* lib/ac-wait.h: Moved the #include ladder that is required to use
+	wait(2) functions here.
+
+	* lib/ac-dirent.h: Moved the #include ladder that is required to
+	use dirent functions here.
+
+	* lib/ac-time.h: Moved the #include ladder that is required to use
+	time functions here, and rewrote all the files that include either
+	<time.h> or <sys/time.h> to instead include "ac-time.h"
+
+	* commands/vpasswds.cc (cli_main): Removed call to srandom.
+
+	* commands/vpasswd.cc (cli_main): Removed call to srandom.
+
+	* commands/vaddusers.cc (cli_main): Removed call to srandom.
+
+	* commands/vadduser.cc (cli_main): Removed call to srandom.
+
+	* lib-cli/main.cc (main): Call srandom here to give all the CLI
+	programs a properly initialized random function automatically.
+
+1999-02-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc: All signal handlers call signal to re-enable
+	signal handling on systems that reset signals.
+
+	* daemon/fork.cc (handle_children): Re-assert the SIGCHLD signal
+	handler after a signal is received, since some systems will reset
+	the behavior of signals after they've been received.
+
+1999-02-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib-cgi/cgi-base.cc (main): Eliminated the timezone setup since
+	it is totally unnecessary.
+
+1999-02-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib-dbi/user.h: Moved the password validation method out of the
+	ruser/vuser classes into struct passcode.  This class may
+	eventually be split into multiple classes, one per passcode type.
+
+1999-02-06  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.86
+
+	* clients/bulletins.cc: Changed logic in all routines to not fail
+	if an error occurrs.
+	(link_file): Fixed several logic flaws.
+
+1999-01-30  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/bulletins.cc: Completed prototype code.
+
+1999-01-28  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/bulletins.cc (scan_bulletins): Roughed-in bulletin
+	scanning support.
+
+	* clients/checkvpw.cc (main): Added call to scan bulletins.
+
+	* lib/configrc.h (class configuration ): Added variables to be
+	used to set up bulletin directories.
+
+1999-01-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vadduser.cc: Modified to accept a "directory" argument
+	of where to put the user's mailbox.
+
+1999-01-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Rewrote various sources to take advantage of new mystring
+	library constructor functions.
+
+	* Inserted revised mystring library.
+
+1999-01-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.85
+
+	* daemon/vpwentry_cache.cc (dirname): Fixed stupid bug -- used
+	"right" instead of "left" to get the directory part of the
+	filename.  This bug was introduced by the following change.
+
+	* All files: reworked code to remove cases where an automatic
+	conversion from type mystring to "const char*' was expected.
+	Instead, all the code uses the c_str() function in mystring.
+
+	* Added a note in the FAQ regarding the default username.
+
+	* lib-cli/main.cc: Rewrote the CLI library to remove dependance on
+	the GNU libiberty getopts.
+
+1998-12-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/vdeliver.cc (main): Changed the default for adding the
+	leading "From " line to false.
+
+	* Released version 0.84
+
+1998-12-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/response_read.cc (read): Removed the __GNUG__ cruft here
+	that was only really necessary to optimize on old "mystring" use
+	(and probably only added nearly useless complexity even then).
+
+	* lib/userdir.cc (userdir): Added a work-around for the apparent
+	egcs inlining bug to fix those core dumps when running vadduser
+	and friends.  Using egcs -finline-functions causes them to core
+	dump, without inlining everything works OK.
+
+1998-12-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vadduser.cc (cli_main): Fixed off-by-one error
+	introduced by the use of lib-cli.
+
+1998-12-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* configure.in: Added a check to determine if the C++ compiler is
+	buggy and abort if so.
+
+1998-12-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* configure.in: Modified the tests for -fno-exceptions and
+	-fno-rtti to actually run the C++ compiler and check its result.
+
+1998-12-02  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/*.cc: Refitted all the command programs to use lib-cli.
+
+1998-11-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vaddalias.cc: Refitted to use lib-cli.
+
+	* lib-cli/main.cc: Wrote a top-level command-line interface
+	helper, which handles automatic help-screen generation, short and
+	long argument parsing, and will eventually handle switching
+	between "standard" command use and server-call usages.
+
+1998-11-28  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/listvdomain.cc: Wrote this program to list the contents
+	of a virtual domain.
+
+	* configure.in: Added a somewhat poor hack to handle support for
+	static vs shared libraries.
+
+	* lib/vpwentry_get.cc: added start_getpw, end_getpw, and getpw
+	routines.
+
+1998-11-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc: Fixed handling of aborted and timed out
+	requests.  A timed out request will result in two error messages,
+	one from the alarm, and one from the failed read.
+
+1998-11-07  Bruce Guenter  <bguenter@hal.qcc.sk.ca>
+
+	* Released version 0.83
+
+	* doc/vmailmgr-cgi.texi: Added a section to describe the use of
+	the listvdomain CGI.
+	
+	* cgi/listvdomain.cc (show_dest): Split original show_user into
+	show_dest which calls show_mbox or show_alias.
+	(show_mbox): Modified output to show mailbox destination.
+	(CGI_MAIN ): Accepts form inputs mboxlink and aliaslink, which are
+	links inserted on each mailbox or alias name, with '%' replaced by
+	the mailbox or alias name.
+
+1998-10-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (handle_connection): It appears that accept may
+	return with an error if a signal occurred while the accept was
+	being processed.  So, loop around accept until a valid fd is
+	returned.
+
+1998-10-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/cgi-*: Moved these files into lib-cgi.
+
+1998-10-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* */*.cc, */*.h: Changed all remaining instances of "const
+	mystring&" to "mystring".
+
+1998-09-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/server.cc, lib/response*.cc: Changed all instances of "const
+	mystring&" to "mystring".
+
+	* cgi/listvdomain.cc (CGI_MAIN ): Forgot to output a content type
+	before the HTML content.  Fixed.
+	(show_domain): The user list is now sorted on output.
+
+	* lib/cgi-args.cc: Changed all instances of "const mystring&" to
+	"mystring".
+
+	* lib/cgi-base.cc: Exported content_type function.
+	Changed all instances of "const mystring&" to "mystring".
+
+1998-09-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.82
+
+1998-09-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (exit_fn): Check the count of active forked
+	processes and sleep until they are all no longer active.
+
+	* daemon/daemon.h: Moved parts of this file into command.h and
+	log.h.
+
+	* daemon/*.cc: Replaced all instances of "cout" that produce log
+	messages with "log()" or "log(msg)".
+
+	* daemon/log.cc (log): Added new routine that prefixes log lines
+	with "[pid] " if the log is being output from a child process.
+
+	* cgi/listvdomain.cc (show_domain): Fixed loop logic to properly
+	truncate the buffer when repeating.  Set up the output to display
+	a table instead of a list.
+	(show_user): Added this routine to output a single user, doing a
+	lookup to determine if the name is a mailbox or alias.
+
+	* daemon/dispatch.cc: Changed all the entries that would modify a
+	user to be "forked" methods.
+
+1998-09-23  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/listdomain.cc (CMD): write_buf returns true on success,
+	not false.  Fixed.
+
+	* lib/response_message.cc (message): Fixed a minor bug: the "msg"
+	portion of the response was treated as a NUL-terminated C string
+	instead of as binary data, causing potential truncation when used
+	with the listdomain facility.
+
+1998-09-21  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/checkvpw.cc (authenticate): Modified to handle extra
+	maildir value in string, eliminating an extra lookup.
+
+	* daemon/check.cc (CMD): Modified return string to include a
+	maildir for virtual users.
+
+	* daemon/fork.cc: Removed all the code that dealt with process
+	slots to fix a race condition: the forked process could exit
+	before the parent registers it as a child, causing the active
+	process counts to become incorrect and eventually prevent any
+	further forks.
+
+1998-09-20  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (handle_connection): Modified to use new fork
+	logic.
+	(usage): Added -v/-V option to usage message.
+
+	* daemon/dispatch.cc (dispatch_cmd): Fixed logic of "did_fork"
+	flag to become two flags: needs_write and needs_exit.
+
+	* daemon/main.cc (main): Removed use of atexit(exit_fn) to
+	automatically remove the socket file, since it must not be removed
+	when exiting from a forked routine.
+
+	* daemon/dispatch.cc (dispatch_cmd): dup2 returns -1, not
+	non-zero, on error.  Fixed.
+
+	* doc/vmailmgr.pod: Added the full list of programs that are part
+	of this package to a "SEE ALSO" list.
+
+1998-09-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/checkvpw.cc (main): Fixed design flaw in the "missing
+	maildir" design caused by setting the MAILDIR environment variable
+	before checking for the existance of the maildir.
+	(find_maildir): Changed search logic -- if no matching string is
+	found, indicate that the last argument is the "maildir" argument.
+	(main): Removed several redundant checks that were a result of the
+	above change.
+
+1998-09-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/response_read.cc (read_response): Fixed the missing "break"
+	in the switch statement.
+
+1998-09-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (handle_intr): Ignore PIPE signals while exiting,
+	as there is a potential for an infinite loop to occur if stdout is
+	a pipe that closes before this program exits.
+
+1998-09-05  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/response_read.cc (receive_string): Moved this routine here
+	from lib/server.cc.
+	(read): Moved the former implementation of response::response(int)
+	into a static read_response routine, and renamed it response::read.
+
+	* lib/server.cc: Fixed several compile bugs.
+
+	* cgi/listvdomain.cc: Fixed compile bugs, still not tested.
+
+1998-08-21  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/listvdomain.cc (CGI_MAIN ): Completed the preliminary
+	implementation of this CGI.
+
+	* lib/server.cc (call): Modified to use the new response
+	constructor to read the response from the client.
+
+	* lib/response.h (struct response): Added a constructor to read
+	the data from a file descriptor.
+
+1998-08-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/lookup.cc (lookup_and_validate): Fixed the behavior when
+	the password table contains a "default" user, the requested user
+	does not exist, and the "mustexist" flag is set.
+
+1998-07-31  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/listvdomain.cc: Started this CGI program to list the users
+	in a virtualdomain, using the new "listdomain" server function.
+
+	* lib/server.h (class server_call): Added a routine 'socket' to
+	return the open socket.
+
+	* lib/server.cc (call): Modified to record the file descriptor for
+	the connection and to close it when the server_call is destructed.
+
+1998-07-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/dispatch.cc (dispatch_cmd): In the case of a forked
+	dispatch, move the output to fd #2 (usually stderr), to give it a
+	constant location.
+
+	* lib/response.h (struct response): Added the 'maxsize' constant
+	representing the maximum size of any one transmitted message.
+
+	* daemon/listdomain.cc (CMD(listdomain)): Completed implementation
+	of this command.
+
+	* daemon/lookup.cc: Moved the functions is_local and find_virtual
+	into this file from dispatch.cc.
+
+1998-07-21  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/listdomain.cc (CMD(listdomain)): Started building this
+	routine to list the users in a virtual domain.
+
+1998-07-20  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (parse_options): Added support for a "verbose"
+	flag.
+
+	* daemon/fork.cc (do_fork): Wrote this new routine to fork a new
+	process and record its pid in a table (if slots are available in
+	the table).
+	(handle_children): Wrote this new routine to handle any children
+	that were forked and have exited.
+
+	* daemon/main.cc (handle_connection): Added support for commands
+	that cause forked connections.
+
+	* lib/configrc.h (class configuration ): Added new configuration
+	variable "max_fork" -- the maximum number of forked processes to
+	handle.
+
+	* daemon/main.cc (handle_connection): Modified this routine to
+	simply close the socket fd and continue if the previous operation
+	forked (the other "half" of the fork will handle the output).
+
+	* daemon/dispatch.cc (struct dispatch ): Added a field to this
+	structure to indicate that the operation needs to fork.
+
+1998-07-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.80
+
+	* clients/checkvpw.cc (getdata): Fixed a longstanding error in
+	setting the password/stamp fields.  Fortunately, this error had no
+	impact at all on the data we use, but would have been immediately
+	visible if we were to try to use the timestamp.
+
+	* daemon/lookup.cc (lookup_virtuser): Added code to look up a
+	default user if the lookup of a named user fails.
+
+	* lib/configrc.h (class configuration ): Added a new configuration
+	variable "default_username".
+
+	* clients/vdeliver.cc (build_command): Fixed a bug that would
+	cause an infinite loop when delivering to multiple destinations.
+	(build_command): Moved the appending of the hostname from enqueue
+	into here, to allow it to be added on each recipient.
+
+1998-06-17  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* doc/vrehash.pod: Started man page for vrehash.
+
+	* commands/vrehash.cc: Wrote this program to move all users
+	directories around into the proper hashed directory (see the man
+	page).
+
+	* commands/vpasswds.cc (change_one): Fixed incorrect status
+	message (was "vpasswd:" should be "vpasswds:").
+
+1998-06-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/maildir.cc (make_maildir): Modified this routine to make all
+	the directories leading up to the named directory.
+
+	* lib/configrc.h (class configuration ): Added the fields
+	user_dir_bits and user_dir_slices to support userdir.
+
+	* lib/vuser_add.cc (vuser_add): Modified an error message to make
+	it more informative.
+
+	* daemon/pwentry.cc (user_dir_abs): Modified to use userdir.
+	(user_dir_rel): Modified to use userdir.
+
+	* lib/vuser_add.cc (vuser_adduser): Modified to use userdir.
+
+	* lib/userdir.cc (userdir): Wrote this routine, which produces a
+	relative user directory name, including a hashed-out path and
+	subdirectories, from a username.
+
+1998-06-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/checkvpw.cc (main): Added a test to check if the user's
+	maildir exists and, if not, set the maildir to the configured
+	"error_maildir" string.
+
+	* daemon/main.cc (handle_intr): Fixed shutdown logic to handle
+	both cases: interrupted while handing a connection, or while
+	waiting for a connection.
+
+	* lib/configrc.h (class configuration ): Added new configuration
+	variable "error_maildir", which is a read-only maildir that
+	contains an error mail message.
+
+1998-06-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/configrc.cc (configuration): Commented out the code to read
+	a local configuration file.
+
+	* lib/configrc.h: Moved the DEFAULT_* definitions out of here and
+	into configrc.cc again.
+
+	* Backed out all the vdomain and configuration patches, in order
+	to fix all the confusion I had been generating.
+
+	* daemon/main.cc (main): Changed the "interrupt" logic to exit
+	after the current request instead of potentially exiting during
+	the request (and leaving files in a indeterminate state).
+
+1998-06-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/vdomain.h (struct vdomain): Added a "config" item to this
+	class.
+
+1998-06-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/state.h (class saved_state): Added code to effectively
+	push/pop a local configuration when entering a saved_state.
+
+	* */*.cc: Changed the use of the "config" variable to account for
+	it being a pointer.
+
+	* commands/*.cc: Added the line "config = local_config();" to the
+	main routine before anything else is executed.
+
+	* lib/configrc.cc (local_config): Added this routine to create a
+	local configuration based on the given home directory.
+
+	* lib/configrc.h: Moved the DEFAULT_* definitions out of here and
+	into configrc.cc (the only place they are referenced).
+	Modified the constructors to support "stacking" of configurations.
+	Made the global "config" variable into a pointer to allow it to
+	change.
+
+	* daemon/vdomain.h (struct vdomain): Wrote this new structure to
+	encapsulate a virtual domain.  These domains are stored in a hash
+	table "vdomains", indexed by base directory.
+
+	* daemon/chpass.cc, daemon/lookup.cc: Adjusted to use the new
+	vdomains global.
+
+	* daemon/pwentry.h (struct pwentry): Removed the vpwentry_cache
+	from this structure.  This will eliminate the expensive lookups at
+	startup (the file "passwd" is looked up for each real user) and a
+	significant amount of memory overhead.
+
+1998-06-05  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.79
+
+1998-06-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/passwdfn.cc: Got rid of __GLIBC__ ifdef for crypt.h
+
+	* lib/pwcrypt.cc: Got rid of __GLIBC__ ifdef for crypt.h
+
+1998-05-31  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/configrc.h: Removed the comment regarding DO_SHADOW.
+
+	* daemon/pwentry_cache.cc: Modified the reader to make only a
+	single pass through the password and shadow password files.
+
+	* lib/configrc.h: Renamed lib/config.h to this to avoid name
+	conflicts with the autoconf/configure-generated config.h.
+
+	* various: Fixups mandated by the use of autoconf.
+
+1998-05-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/dispatch.cc: Made the "echo" daemon command conditionally
+	compiled if TEST_DAEMON is defined.
+
+	* daemon/vpwentry_cache.cc: Added code to log when the virtual
+	password caches are loaded/reloaded.
+
+	* daemon/pwentry_cache.cc: Added code to log when the password
+	cache is loaded/reloaded.
+
+	* commands/vsetup.cc (setup_passwd): Modified to use the new
+	postmaster config variables.
+
+	* lib/config.cc (read_config): Changed the "postmaster"
+	configuration variable into "postmaster_email" and added
+	"postmaster_aliases".
+
+1998-05-27  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.78
+
+	* lib/vpwentry_putpw.cc (putpw): Fixed logic to deal with an
+	existant but non-readable original password file.
+
+	* lib/vuser_add.cc (vuser_add): Changed the order of creating the
+	maildir and adding the user to the passwd file.  This allows the
+	maildir to be erased if adding the user fails, since the newly
+	created maildir is guaranteed to be empty.
+
+	* lib/maildir.cc (make_maildir): Modified the code to remove any
+	newly-created directories if creation of any directory fails.
+
+	* lib/passwdfn.cc (getpasswd_stdin): Changed use of "gets" to
+	"cin.get".
+
+1998-05-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vpasswd.cc (main): Changed the "fprintf" to use
+	IOStreams.
+
+	* lib/passwdfn.cc (getpasswd_*): Print a warning if the password
+	is longer than 8 characters.
+
+	* commands/vpasswds.cc: Wrote this new program to change the
+	passwords of a list of users.  The input for this list is taken
+	from standard input and is of the form "name password".  Anything
+	following the password is ignored.
+
+	* lib/config.cc: Added a new configuration item: postmaster.
+
+	* commands/vadduser.cc (main): Removed the call to setup.
+
+	* commands/vaddusers.cc (main): Removed the call to setup.
+
+	* commands/vsetup.cc: Wrote this program to set up a new virtual
+	domain with the proper ".qmail-default" file and a users
+	directory, along with some useful system aliases.
+
+	* daemon/vpwentry_cache.cc (write): Use "rename" system call.
+
+	* lib/vpwentry_putpw.cc (putpw): Use "rename" sytem call.
+
+	* lib/vpwentry_delpw.cc (delpw): Use "rename" system call instead
+	of "unlink/link/unlink" combination to guarantee atomicity of the
+	operation.
+
+	* commands/_setup.cc (setup): Moved this routine out of
+	vadduser.cc so that it could be shared with vaddusers.cc.  It
+	should probably go into the shared library under a different
+	name.
+
+	* commands/vaddusers.cc: Wrote this new program that adds a list
+	of users.  The input for this list is taken from standard input
+	and is of the form "name password [alias ...]".
+
+	* lib/vpwentry_putpw.cc (putpw): Fixed a bug in the logic that
+	prevented the temporary password file from being renamed to a
+	non-existant original file.
+
+1998-05-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.77
+
+	* lib/vpwentry_putpw.cc (putpw): Fixed bug that would cause a
+	failed addition to leave behind a temporary file as well as merged
+	the case if the file does not already exist.
+
+1998-05-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/pwentry_cache.cc: Fixed this code to deal with shadow
+	passwords.  Thanks to Andrew Gillespie for the initial patch to
+	show the problems.  The new code properly deals with caching both
+	the contents of /etc/shadow and /etc/passwd, as well as handling
+	the case where shadow passwords don't exist.
+
+1998-05-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.76
+
+	* daemon/file_cache.h (write_file): Call force_valid to avoid
+	having to re-read the cached table immediately after having
+	written its contents.  Do this _before_ unlocking the directory to
+	avoid a race condition.
+
+	* daemon/file_cache.cc (force_valid): Added this routine to force
+	the cache state to indicate that the file is valid (if the file is
+	present).
+
+1998-05-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/dispatch.cc (find_virtual): Fixed bug preventing use of
+	wildcards in virtualdomains.
+
+1998-05-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/vpwentry_cache.cc (write): Set the new file mode to 0600.
+
+	* lib/vpwentry_putpw.cc (putpw): Set the new file mode to 0600,
+	not 0700 (no execute bit).
+
+1998-05-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/vpwentry_cache.cc (operator): Modified code to delete
+	entries that fail insertion into the table (ie duplicates).
+
+	* daemon/chpass.cc (CMD): Removed the calls to begin/end_modify.
+
+	* daemon/file_cache.h (file_cache_writer::write_file): Removed the
+	begin/end_modify routines and bundled them into this routine.
+
+1998-05-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/vpwentry_cache.cc (unlock): Fixed bug in unlocking the
+	directory.
+
+	* daemon/chpass.cc (CMD): Modified to use the file cache to modify
+	the password table instead of the vuser_chpass routine.
+
+1998-05-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.75
+
+	* daemon/main.cc (TIMEOUT): Changed the connection timeout to one
+	second, as values larger than that are useful only for debugging
+	the connection handling code.
+
+	* lib/vpwentry_putpw.cc (putpw): Modified to use '\n' instead of
+	the endl operator to mark line ends.
+
+	* lib/vpwentry_delpw.cc (delpw): Modified to use '\n' instead of
+	the endl operator to mark line ends (allows the output stream to
+	properly buffer writes).
+
+1998-05-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* clients/checkvpw.cc, clients/vdeliver.cc: Moved these to files
+	from "commands" to the "clients" subdirectory
+
+	* daemon/pwentry_cache.cc (operator): Convert the user names to
+	lowercase before inserting.
+
+	* daemon/vpwentry_cache.cc (operator): Fixed bug: make the
+	virtual users' names lowercase before inserting into the table.
+
+	* daemon/check.cc (CMD): Fixed bug: initialize virtpw pointer.
+
+	* daemon/lookup.cc (lookup_maildir): Removed obsolete routine.
+	(CMD): Fixed bug: must initialize the pointers that previously
+	used autodelete.
+
+	* daemon/vpwentry_cache.cc (operator): Fixed a bug that caused the
+	password and destination strings to be both stored in the password
+	field.
+
+	* daemon/file_cache.cc (validate_cache): Check both the last
+	modification time on the file and the inode number to determine if
+	the file has changed.
+
+	* daemon/*.cc: Changed all variables of type "autodelete<vpwentry>"
+	back to type "vpwentry*".
+
+	* daemon/pwentry.cc: Removed the "getpw_byname" routine, now
+	obsoleted by the pwentry_cache.
+
+	* daemon/lookup.cc (lookup_virtuser): Modified to handle the new
+	vpwtable cache in the pwentry.
+
+	* daemon/pwentry.cc (pwentry): Initialize the vpwtable on
+	creation.
+
+	* daemon/pwentry.h (struct pwentry): Added a vpwentry_cache to
+	this object.
+
+	* daemon/vpwentry_cache.cc (write): Changed the end-of-line marker
+	from endl to "\n", as endl will cause the buffer to be flushed.
+
+	* daemon/main.cc (read_data): Removed support for protocol one
+	requests (which allows me to remove one more read syscall from the
+	fast path, shrinking it down to a total of two reads).
+
+1998-05-06  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (read_data): Modified to read messages using
+	either protocol one or two.
+
+	* lib/server.cc (build_msg): Modified to build messages using
+	protocol 2.
+
+	* daemon/qmail.*: Removed these obsolete source files.
+	
+	* daemon/dispatch.cc (find_virtual): Wrote this routine that
+	mimics the old behavior of find_virtual from qmail.cc to find a
+	mapping from a virtual domain name to a prefix, using a map_cache
+	on control/virtualdomains.
+
+	* daemon/file_cache.h (class file_cache): Modified the behavior to
+	automatically load the cache on construction, instead of waiting.
+
+	* daemon/map_cache.h: Wrote the classes for map_cache, a generic
+	qmail-style map-file cache (the key and value pair is separated by
+	a colon, one per line).
+
+	* daemon/list_cache.h: Renamed locals_cache to list_cache, as a
+	generic list-file cache class.
+
+	* daemon/dispatch.cc (is_local): Fixed to check the cached result.
+
+	* daemon/file_cache.cc: Moved the actual code for file_cache_base
+	here.
+
+	* daemon/file_cache.h (class file_cache_base): Created this class
+	to contain the common code in the file_cache template.
+
+	* daemon/lookup.cc (lookup_baseuser): fixed the lookup to only
+	read the cached "pwentries" object once per invocation, and to
+	check the result.
+
+	* daemon/qmail.cc (is_local): Removed this routine, as its
+	functionality can be duplicated with a locals cache.
+
+	* daemon/locals_cache.cc: Wrote this object to cache the "locals"
+	table used by qmail to determine what domains are "local".
+
+	* daemon/qmail.cc: Moved this object here from lib.
+
+	* daemon/*.cc: Changed all variables of type "autodelete<pwentry>"
+	back to type "pwentry*", as the lookup functions that would set
+	these variables now return non-deletable references.
+	
+	* daemon/lookup.cc: Modified the various lookup routines that look
+	up base users to use the pwentries cache.
+
+	* daemon/file_cache.h:
+	* daemon/hash_table.h:
+	* daemon/crc32.h:
+	* daemon/crc32.cc:
+	* daemon/crc_hash.h:
+	* daemon/pwentry_cache.cc: 
+	* daemon/pwentry_cache.h: 
+	* daemon/vpwentry_cache.cc: 
+	* daemon/vpwentry_cache.h: Merged from temporary development
+	tree.  Current functionality consists of a generic hash table,
+	mapping from mystring keys to generic objects; a file cache that
+	will automatically reload a cached object only when necessary; and
+	specific code for building caches of the base user password table
+	(pwentry_cache) and virtual password tables (vpwentry_cache).
+
+	* lib/vpwentry_putpw.cc (putpw): Now opens the temporary file with
+	"noreplace" to avoid races, and mode 0700.
+
+	* lib/vpwentry_delpw.cc (delpw): Now opens the temporary file with
+	"noreplace" to avoid races, and mode 0700.
+
+1998-05-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/pwentry.*: Moved these files here from lib, as no other
+	module uses them.
+
+	* lib/pwentry.cc (getpw_byname): Moved this function here from
+	pwentry_getpw.cc.
+
+	* lib/vpwentry_delpw.cc: Renamed this file from pwentry_delpw.cc
+
+	* lib/vpwentry_putpw.cc: Renamed this file from pwentry_putpw.cc
+
+	* lib/vpwentry_getpw.cc: Added the getpw_byname function from
+	pwentry_getpw.cc.
+
+	* lib/pwentry_getpw.cc: Removed the vpwentry function.
+
+1998-05-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/vuser.h: Only include "vpwentry.h", not "pwentry.h"
+
+	* lib/vpwentry.cc: Moved the vpwentry constructors and destructors
+	here.
+
+	* lib/pwentry.cc: Removed the vpwentry portions.
+
+	* lib/pwentry.h: Removed the portions that only deal with
+	vpwentry's.
+
+	* lib/vpwentry.h: Split the portions of pwentry.h that only deal
+	with vpwentry's into this file.
+
+	* spec: Forgot to add a call to "ldconfig" in %post.
+
+1998-04-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.74.
+
+1998-04-23  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/chpass.cc (CMD): modified to use save_state.
+
+	* daemon/deluser.cc (CMD): modified to use save_state.
+
+	* daemon/delalias.cc (CMD): modified to use save_state.
+
+	* daemon/addalias.cc (CMD): modified to use save_state and
+	lookup_and_validate.
+	
+	* daemon/adduser.cc (CMD): Modified to use save_state.
+
+	* daemon/state.h (class saved_state): Created this class from
+	saved_uidgid -- it also does a chdir to the user's home
+	directory.  By doing so, it allows the use of relative paths as if
+	operating as the given user.
+
+	* daemon/lookup.cc (lookup_and_validate): Modified to optionally
+	create a new vpwentry if the named virtual shouldn't and doesn't
+	exist yet.
+
+	* daemon/adduser.cc (CMD): Modified to use lookup_and_validate and
+	pwentry::user_dir_rel.
+
+	* lib/pwentry.cc (user_dir_rel, user_dir_abs): Created these two
+	routines that return the relative (to home) and absolute directory
+	name of a new virtual user's directory according to the configured
+	user_dir parameter.
+
+	* commands/checkvpw.cc: Added function declarations missing on
+	Solaris.
+
+	* commands/vdeliver.cc: Added function declarations missing on
+	Solaris.
+
+	* lib/cgi-base.cc: Added function declarations missing on Solaris.
+
+	* commands/vpasswd.cc: Added function declarations missing on
+	Solaris.
+
+	* commands/vadduser.cc: Added function declarations missing on
+	Solaris.
+
+	* lib/pwcrypt.cc: Added function declarations missing on Solaris.
+
+	* daemon/dispatch.cc (dispatch_cmd): Add the domain name to the
+	error message for an invalid domain name, as the request won't
+	have been printed by the time this happens.
+
+1998-04-21  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vadduser.cc (add_alias): Fixed bug: this routine
+	previously looked up the user name instead of the alias when
+	checking for the existance of the alias.
+
+	* lib/validate.cc (validate_field): Fixed bug: find_first returns
+	-1 if nothing is found, not zero.
+
+	* commands/vadduser.cc (add_alias): No longer necessary to add the
+	'&' prefix.
+
+	* commands/vaddalias.cc (main): No longer neccessary to add the
+	'&' prefix.
+
+	* lib/vuser_add.cc (vuser_addalias): Automatically prepend a '&'
+	to the destination.
+
+	* daemon/addalias.cc (CMD(addalias)): Call validate_redirect
+	before adding the alias.
+
+1998-04-17  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vaddalias.cc (main): Removed the destination validation
+	code from this program and made it call validate_redirect.
+
+	* lib/validate.cc (validate_redirect): Created this routine to
+	validate a redirect destination.
+
+1998-04-16  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/validate.cc (validate_username): Revised this to disallow
+	'/' in user names.
+
+	* vmailmgr.conf.sample: Added notes regarding which component(s)
+	uses each of the listed settings.
+
+	* lib/config.h: Removed the macro definitions that just served as
+	aliases for parts of the configuration class.
+
+1998-04-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/lookup.cc: Removed the 'userlookup' routine.
+
+	* lib/maildir.cc (make_maildir): Moved this routine here from
+	vuser_add.
+	(delete_maildir): Moved this routine here from vuser_deluser,
+	renamed from deltree.
+
+1998-04-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/vuser_add.cc (vuser_add): Use validate routines instead of
+	hard-coded checks.
+	(vuser_adduser): Renamed the simple vuser_add to vuser_adduser to
+	avoid confusion between the two vuser_add routines.
+
+	* lib/validate.cc (validate_username): Wrote this routine to
+	ensure that a username is valid; returns true if so.
+
+	* daemon/delalias.cc (CMD(delalias)): Switched from userlookup to
+	lookup_and_validate.
+
+	* daemon/addalias.cc (CMD(addalias)): Switched from userlookup to
+	lookup_{baseuser,virtuser}.  Removed check for invalid alias name
+	(already done by vuser_addalias).
+
+	* daemon/deluser.cc (CMD(deluser)): Switched from userlookup to
+	lookup_and_validate.
+
+	* daemon/adduser.cc (CMD(adduser)): Switched from userlookup to
+	lookup_{baseuser,virtuser}.  Removed check for invalid user name
+	(already done by vuser_add).  Removed duplicated code from
+	vuser_adduser.
+
+	* daemon/check.cc (CMD(check)): Switched from userlookup to
+	lookup_{baseuser,virtuser}.
+
+	* daemon/chpass.cc (CMD(chpass)): Switched from userlookup to
+	lookup_and_validate.
+
+	* daemon/lookup.cc (lookup_and_validate): Wrote this routine,
+	which looks up base and virtual users and validates them,
+	replacing several lines of common code in many of the interfaces.
+
+	* commands/checkvpw.cc (main): Use the separators configuration
+	item instead of just '@'.
+
+	* lib/config.cc (read_config): Added a new configuration option,
+	"separators", which lists valid separators between the user name
+	and virtual domain name when logging in via checkvpw.  Defaults to
+	"@:"
+
+	* lib/mystring.cc (find_first): Added this routine, finds the
+	first character that matches any one in a set.
+
+	* daemon/lookup.cc (userlookup): Split this function into its two
+	parts, lookup_baseuser and lookup_virtuser.
+
+1998-04-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vaddalias.cc (main): Modified this code to handle (and
+	check) multiple recipients.
+
+	* commands/vdeliver.cc (enqueue): Split this routine into three
+	parts, and added the functionality to deal with multiple
+	recipients in a destination address (separated by commas).
+
+1998-04-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeliver.cc (enqueue): Changed the calls to setenv to
+	equivalent calls to putenv, as some system's don't have setenv.
+
+	* commands/checkvpw.cc (set_environ): Changed the calls to setenv
+	to equivalent calls to putenv, as some system's don't have setenv.
+
+1998-04-05  Bruce Guenter  <bguenter@hal.qcc.sk.ca>
+
+	* Released version 0.73
+
+	* commands/vdeliver.cc (main): Fixed bug with handling of ??LINE
+	environment variables (local variables had erroneously overridden
+	previously global variables).
+
+	* vmailmgr-cgi.texi: Filled in the details for the form fields of
+	vpasswd.
+
+	* cgi/*.cc: Remove the "CGI_INPUT" lines for "vdomain" and
+	"password", as they are defined by the top-level CGI constructor.
+
+	* lib/cgi-base.cc (CGI): Add "vdomain" and "password" to the list
+	of fields that are automatically retrieved for all the CGIs, as
+	all CGIs will operate on a virtual domain, and all require a
+	password.
+
+1998-04-02  Bruce Guenter  <bguenter@hal.qcc.sk.ca>
+
+	* vmailmgr-cgi.texi: Started writing documentation on how to
+	configure the CGI programs.
+
+1998-04-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* HOWTO.texi: Started writing instructions on how to do certain
+	tasks with vmailmgr.
+
+1998-03-31  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/config.cc (read_config): Rewrote this routine to only go
+	through the file once (instead of once per variable), and to print
+	out errors on invalid lines.
+
+1998-03-29  Bruce Guenter  <bguenter@hal.qcc.sk.ca>
+
+	* various: Use pwentry::pwfile and pwentry::user_dir in place of
+	computing their values repeatedly.
+
+	* lib/pwentry.cc (pwentry::pwfile): Wrote this routine, returns
+	the password file name for the given base user.
+	(pwentry::user_dir): Returns the user directory for the given base
+	user.
+
+	* lib/config.cc (post_process): Wrote this routine to "tidy up"
+	some of the configuration strings, such as directories that should
+	always have a trailing slash ('/').
+
+	* lib/config.h: Change all the defined configuration macros
+	(except for DO_SHADOW) to their configuration variables.
+
+	* various: Treat the configuration defines as variables instead of
+	as constant strings.
+
+	* lib/config.cc (configuration): Initialize all the strings to
+	default values.
+
+1998-03-28  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/config.cc: Started this module, which can read a
+	configuration file for default values at runtime.  The default
+	configuration initialization will read both a global configuration
+	file and a local one.
+
+1998-03-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.72
+
+	* commands/vdeliver.cc (main): Fixed the bug that caused empty
+	environment variables (valid) to be treated as non-existant
+	environment variables.  This caused bounces to vdeliver to double
+	bounce.
+
+	* Released version 0.71
+
+1998-03-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi/*.cc: Use "msg", not "message()" from the response as the
+	error response message.
+
+	* lib/cgi-args.cc (get_parts): Strings weren't being terminated
+	properly before being set.  Fixed.
+
+1998-03-20  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/dispatch.cc: Added entries for deluser, delalias, and
+	addalias.
+
+	* daemon/delalias.cc (CMD(delalias)): Wrote this routine to delete
+	an alias.
+
+	* daemon/addalias.cc (CMD(addalias)): Wrote this routine to add an
+	alias.
+
+	* cgi: Merged in all the code and libraries for CGI programs into
+	the standard build.  At this point, there is a basic framework
+	that all CGI programs will use, which includes a mechanism that
+	automatically pulls the inputs from a POST form, and a base class
+	that is executed on startup.  The CGI module defines the routine
+	CGI_MAIN, which is executed by the program startup code.  The CGI
+	module should call either error() or success() at the end of its
+	execution, which will handle printing out an appropriate message.
+	All of the v* programs (vpasswd, vadduser, vdeluser, vaddalias,
+	and vdelalias) have a CGI equivalent.
+
+	* daemon/deluser.cc (CMD(deluser)): Wrote this routine to delete a
+	user.
+
+1998-03-19  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/server.cc: include un.h
+
+	* daemon/main.cc: include un.h
+
+	* lib/un.h: Wrote this header to define SUN_LEN and to include
+	necessary things for doing sockets.
+
+	* daemon/main.cc (make_socket): Split the code to create a socket
+	into this routine; fixed the permissions bug that caused the
+	socket to be created without other-write permission when launched
+	with a non-zero umask.
+
+	* Released version 0.70
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/INSTALL	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,14 @@
+if WANTPYTHON
+SUBDIRS = python php lib authenticate commands daemon cgi doc scripts
+else
+SUBDIRS = php lib authenticate commands daemon cgi doc scripts
+endif
+
+dist-hook:
+	cp -dP `find lib/ac -name CVS -prune -o \( -not -name '*~' -a -type f -o -type l \) -print` $(distdir)
+	sed -e s/@VERSION\@/@VERSION@/ <spec >$(distdir)/vmailmgr-@VERSION@.spec
+
+docs:
+	$(MAKE) -C doc all
+	$(MAKE) -C daemon docs
+	$(MAKE) -C commands docs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,379 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+@WANTPYTHON_TRUE@SUBDIRS = python php lib authenticate commands daemon cgi doc scripts
+@WANTPYTHON_FALSE@SUBDIRS = php lib authenticate commands daemon cgi doc scripts
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = 
+DIST_COMMON =  README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \
+Makefile.am Makefile.in NEWS TODO acconfig.h acinclude.m4 aclocal.m4 \
+config.h.in configure configure.in install-sh missing mkinstalldirs
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DIST_SUBDIRS =  python php lib authenticate commands daemon cgi doc \
+scripts php lib authenticate commands daemon cgi doc scripts
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4):  configure.in  acinclude.m4
+	cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+	cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+	@if test ! -f $@; then \
+		rm -f stamp-h; \
+		$(MAKE) stamp-h; \
+	else :; fi
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES= CONFIG_HEADERS=config.h \
+	     $(SHELL) ./config.status
+	@echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+	@if test ! -f $@; then \
+		rm -f $(srcdir)/stamp-h.in; \
+		$(MAKE) $(srcdir)/stamp-h.in; \
+	else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
+	cd $(top_srcdir) && $(AUTOHEADER)
+	@echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+	-rm -f config.h
+
+maintainer-clean-hdr:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive  \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+	@set fnord $(MAKEFLAGS); amf=$$2; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@set fnord $(MAKEFLAGS); amf=$$2; \
+	dot_seen=no; \
+	rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+	  rev="$$subdir $$rev"; \
+	  test "$$subdir" = "." && dot_seen=yes; \
+	done; \
+	test "$$dot_seen" = "no" && rev=". $$rev"; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+	    test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	-rm -rf $(distdir)
+	GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+	mkdir $(distdir)/=build
+	mkdir $(distdir)/=inst
+	dc_install_base=`cd $(distdir)/=inst && pwd`; \
+	cd $(distdir)/=build \
+	  && ../configure --srcdir=.. --prefix=$$dc_install_base \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist
+	-rm -rf $(distdir)
+	@banner="$(distdir).tar.gz is ready for distribution"; \
+	dashes=`echo "$$banner" | sed s/./=/g`; \
+	echo "$$dashes"; \
+	echo "$$banner"; \
+	echo "$$dashes"
+dist: distdir
+	-chmod -R a+r $(distdir)
+	GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+	-rm -rf $(distdir)
+dist-all: distdir
+	-chmod -R a+r $(distdir)
+	GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+	-rm -rf $(distdir)
+distdir: $(DISTFILES)
+	-rm -rf $(distdir)
+	mkdir $(distdir)
+	-chmod 777 $(distdir)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+	for subdir in $(DIST_SUBDIRS); do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d $(distdir)/$$subdir \
+	    || mkdir $(distdir)/$$subdir \
+	    || exit 1; \
+	    chmod 777 $(distdir)/$$subdir; \
+	    (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am: all-am
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+all-recursive-am: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am:
+install-exec: install-exec-recursive
+
+install-data-am:
+install-data: install-data-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am:
+uninstall: uninstall-recursive
+all-am: Makefile config.h
+all-redirect: all-recursive-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-hdr mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am:  clean-hdr clean-tags clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am:  distclean-hdr distclean-tags distclean-generic clean-am
+
+distclean: distclean-recursive
+	-rm -f config.status
+
+maintainer-clean-am:  maintainer-clean-hdr maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+install-data-recursive uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs-am \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+dist-hook:
+	cp -dP `find lib/ac -name CVS -prune -o \( -not -name '*~' -a -type f -o -type l \) -print` $(distdir)
+	sed -e s/@VERSION\@/@VERSION@/ <spec >$(distdir)/vmailmgr-@VERSION@.spec
+
+docs:
+	$(MAKE) -C doc all
+	$(MAKE) -C daemon docs
+	$(MAKE) -C commands docs
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NEWS	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,455 @@
+-------------------------------------------------------------------------------
+Changes in version 0.96.9
+
+New Features:
+- vdeluser now has an option to prevent it from deleting users with a
+  mailbox.
+- All the Python CGI code has been dropped.  A stand-alone vpyadmin
+  package (to be release very shortly) will replace the Python CGIs.
+  Between this new interface and the PHP code, the C++ CGIs are
+  depricated and will be removed in a future version, unless somebody
+  violently objects.
+
+Internal Changes:
+- Cleaned up the vpwtable API.
+- New CLI documentation generator, should help keep the man pages and
+  the programs in sync.
+- Major overhaul to the Python library.
+
+Bug Fixes:
+- Fixed error handling in vdeliver to properly handle file-system quota
+  errors.
+- Fixed a bug in the Courier IMAP authentication module that prevented
+  non-virtual users from authenticating.
+- The daemon now exits immediately if a SIGALRM or SIGPIPE is caught,
+  instead of completing the action.
+- Fixed a bug in autodetecting Python.  It should now work with any
+  version of make.
+-------------------------------------------------------------------------------
+Changes in version 0.96.8
+
+New Features:
+- Added a quota checking program for use in vdeliver-predeliver.
+- The authvmailmgr Courier-IMAP auth module now executes
+  authvmailmgr-presetuid and authvmailmgr-postsetuid before and after
+  executing the setuid respectively, just like checkvpw.
+
+Internal Changes:
+- The daemon lookup command now returns all of the virtual user data,
+  not just the mailbox and forwarding.
+
+Bug Fixes:
+- Fixed a typo in the vmailmgrd run script.
+- Fixed a bug in the daemon that would cause actions to be applied to
+  the default virtual user if the named virtual user did not exist.
+- Fixed a bug in the daemon that would allow disabled autoresponders to
+  be written to.
+- Fixed a bug in the subprogram execution code that would cause the
+  wrong exit status to be returned.
+- vdeliver now rewinds standard input before executing postdeliver.
+- The autoresponse daemon command will now read the disabled
+  autoresponse file if the enabled one does not exist.
+- Fixed note on setting up a domain in the HOWTO.
+- Fixed a bug in the fdbuf library.
+-------------------------------------------------------------------------------
+Changes in version 0.96.7
+
+New Features:
+- Contains configure-time switchable support for GDBM virtual user tables.
+- Added a new utility, vpasswd2db, to convert a plain text password
+  table into whatever vpwtable format is configured.  This utility will
+  be much slower than vpasswd2cdb for CDB files (for now), so only use
+  it for other (ie GDBM) formats.
+
+Internal Changes:
+- Updated PHP code.
+- The daemon now relies on ucspi-unix to handle connections and forking
+  instead of doing it internally.
+- The autoresponse is written into a new subdirectory of the virtual
+  user's mailbox directory.  This makes it work better with the
+  autoresponder, which requires a directory to store temporary files in.
+- Reorganized the vpwtable code somewhat.
+
+Bug Fixes:
+- The daemon now initializes its random number generator each time it
+  handles a command, which should make it generate different salts for
+  password hashes.
+- The python subdirectory no longer requires GNU make to build, and
+  should no longer build at all if Python cannot be located.
+-------------------------------------------------------------------------------
+Changes in version 0.96.6
+
+New Features:
+- Added autoresponse command to daemon, modified from code submitted by
+  Mike Bell.  This allows the user to upload a autoresponse file to
+  their virtual mailbox, to be used by an autoresponder (not included).
+- Added autoresponse CGI written in Python, as well as updated Python
+  library code.
+- Updated PHP code from Mike Bell.
+- Replaced the FAQ and HOWTO documents with the revised ones by Dan
+  Kuykendall.
+
+Internal Changes:
+- The necessary parts of the Courier IMAP "authlib" library is now
+  included in this package.  The Courier IMAP authentication module is
+  now always built.
+- The Courier IMAP module is now part of the standard RPM.
+
+Bug Fixes:
+- Fixed a problem with converting from old records that didn't set the
+  virtual user flags properly.
+- Fixed a problem with the virtual user creation time field not being
+  set properly.
+- Fixed a bug in vdeliver that would cause any error from the predeliver
+  script to be treated as a temporary failure.
+- Fixed a bug in the domain name lookup code that caused case sensitive
+  domain name comparisons.
+-------------------------------------------------------------------------------
+Changes in version 0.96.5
+
+New Features:
+- Mailbox delivery can be temporarily disabled on a per-virtual-user
+  basis, through either the CGIs, command-line tools, or PHP, without
+  deleting the mailbox.
+- Account expiry is handled by the authentication tools and by vdeliver.
+
+Internal Changes:
+- The binary record format has changed to handle the new boolean flags.
+  Note that this new format is backwards compatible, so no conversion is
+  needed.
+
+Bug Fixes: None
+-------------------------------------------------------------------------------
+Changes in version 0.96.4
+
+New Features:
+- Added an upgrading section in the FAQ.
+- The command-line tools now have a "--quiet" option to suppress all
+  status messages.
+- Added a "vchforwards" CGI interface.
+- Modified the "vaddalias" CGI program to accept a comma-seperated list
+  of destinations.
+- Added some sample HTML pages for the CGIs.
+
+Internal Changes:
+- Minor updates to the mystring and fdbuf libraries.
+
+Bug Fixes:
+- Fixed a problem that caused the Courier IMAP authentication module to
+  fail for users of the form "baseuser-virtuser".  It should work now.
+-------------------------------------------------------------------------------
+Changes in version 0.96.3
+
+New Features: None
+
+Internal Changes:
+- Removed the "include" directory.
+- Made vpwtable & vpwentry a seperate source directory.
+- Merged the "adduser", "addalias", and "addaliasp" daemon interfaces
+  into one new inteface named "adduser2".  The C++ CGIs and the PHP3
+  code has been modified to use the new interface.
+
+Bug Fixes: None
+-------------------------------------------------------------------------------
+Changes in version 0.96.2
+
+New Features:
+- Updated the FAQ, and added some new answers.
+- Added a Courier IMAP authentication module.  This module does not yet
+  work, unfortunately.
+- Tossed the existing non-functional PHP3 module and added a working one
+  (written in PHP3) from Mike Bell.
+- Modified vsetup to call programs before and after setting up the
+  domain.
+- Added new "vauthenticate" command.
+- Turned the small vaddalias program into a simple shell script.
+
+Internal Changes:
+- Moved the Python code into its own directory, like the PHP3 stuff.
+- Moved the checkvpw module into an "authenticate" directory.
+- Imported changes to the CLI library to make it behave more like the
+  standard getopt.
+
+Bug Fixes:
+- Fixed some bugs in the Kerberos5 configuration handling.
+-------------------------------------------------------------------------------
+Changes in version 0.96.1
+
+New Features:
+- Output of listvdomain CGI has changed slightly to reflect the change
+  in internal data structures.
+
+Internal Changes:
+- Changed listdomain daemon protocol to speed up domain listings and to
+  allow for more information (not yet present in the listdomain CGI).
+
+Bug Fixes:
+- Fixed bug in building Python code from input files with non-GNU make.
+-------------------------------------------------------------------------------
+Changes in version 0.96
+
+New Features:
+- Record data format has been enhanced to add personal information,
+  simple quotas, and expiry information, plus other extra data.
+- Messages can now be delivered to both a mailbox and a list of
+  forwarding addresses at once.
+- Programs executed from checkvpw or vdeliver will have all the above
+  data set in environment variables.
+- listvdomain can now list only users, only aliases, or selected names.
+- The listvdomain CGI has improved formatting ability.
+- Preliminary support for Kerberos5 authentication.  Please tell me if
+  this works for you if you need this, as I can't test it myself.
+- New "vchattr" command to change a virtual user's attributes.
+- New "vchforwards" command to change the forwarding addresses of a
+  user.
+- Executable configuration settings are treated as executable files
+  rather than lists of statements to execute.
+
+Internal Changes:
+- Record parsing routines will read either record format but will write
+  out new record format.
+- Daemon command dispatching now requires seperate virtual domain and
+  virtual user arguments (all the CGIs do this anyways), as opposed to
+  allowing "baseuser-virtual".
+
+Bug Fixes:
+- Fixed non-portable increment statement in vconf2dir shell script, as
+  well as a couple of other bugs.
+- Fixed bug in vdeliver that would cause it to loop without sleeping
+  when it couldn't write to the output file.
+
+NOTES:
+- I would consider this an unstable release.  Adding and deleting users,
+  delivery, and password checking have been tested, but little else.  I
+  just want to get this out.  There are so many big changes in this one
+  that there are bound to be unexpected bugs.
+- Despite the change in the record format, no password table upgrading
+  will be necessary, as this version can read in both new and old
+  records.
+- The "vaddalias" command has been superceeded by "vadduser -D".
+- The "vchalias" command has been replace with "vchforwards".
+- The "vdelalias" command has been removed since "vdeluser" does both
+  jobs.
+- Support for quota management and account expiry are not included yet.
+- The C++ CGIs are limited to adding aliases with a single forwarding
+  address.  The generic Python CGI can be used to create users with
+  multiple forwarding addresses.  I intend to remove most or all of the
+  C++ CGIs in favour of a more generic interface.
+-------------------------------------------------------------------------------
+Changes in version 0.95
+
+New Features:
+- vdeliver now has a hook to execute a list of programs before and after
+  delivering an email.  See doc/configuration.* for full details.
+- checkvpw now has a hook to execute a list of programs before and after
+  changing its uid, and after executing the subprogram
+- The bulletins facility is now a standalone program called vpopbull.
+- There is a new program showvconfig which can list the configuration
+  information.
+
+Internal Changes as above.
+
+Bug Fixes:
+- The call to execl in vdeliver when calling qmail-queue was missing a
+  parameter.
+-------------------------------------------------------------------------------
+Changes in version 0.94
+
+New Features:
+- vdeliver and checkvpw no longer call up to vmailmgrd to do user
+  lookups and authentication.  This makes them significantly faster,
+  since the daemon no longer does any useful memorization of any kind of
+  data (no password or virtualdomains caches, etc.), and the socket
+  connection and fork took significant amounts of time.
+
+Internal Changes:
+- The virtual user and virtual password table manipulation were moved
+  into a class interface.  This will be (once the password content
+  changes are integrated in the next couple of versions) the official
+  API target for building alternative database backends (like the much
+  requested MySQL interface).
+- Removed the "check" command from the daemon, since it's no longer
+  used.
+
+Bug Fixes:
+- vdeliver still used a hard coded /var/qmail instead of
+  config->qmail_root().
+
+NOTES:
+* You will no longer need to have vmailmgrd running to use checkvpw,
+  vdeliver, and the command-line tools.  You only need vmailmgrd (and
+  the vmailmgr-daemon RPM package) if you need to use the CGIs.
+-------------------------------------------------------------------------------
+Changes in version 0.93
+
+New Features:
+- New configuration system, based on individual files per configuration
+  parameter rather than one big file.  Should be more extensable this
+  way, and has been benchmarked to be faster.  The configuration files
+  are documented in the configuration.{html,texi,txt} files.
+- New configuration system also set up to allow domain-local
+  configurations by putting a directory named ".vmailmgr" in the domain
+  directory.  This IS (unlike my last attempt) read properly by the
+  daemon and all the utilities and clients.  The daemon switches over to
+  checking for local configuration items immediately after determining
+  what user/domain is being handled.
+- A new "qmail-root" configuration parameter to allow for installations
+  where qmail is not installed in /var/qmail.
+
+Internal Changes:
+- All the v* commands now do a chdir to $HOME before continuing.
+- A virtual domain class has been set up, and is used to reference each
+  domain through a user, with both a user-local and domain-local
+  configuration structure.  This will shortly be used to set up multiple
+  virtual domains per user.
+- Imported new and improved mystring and fdbuf libraries.
+
+Bug Fixes:
+- The .qmail-default file is created with mode r--r--r-- to prevent
+  qmail problems with a writable delivery file in situations where the
+  umask is less restrictive than 022.
+
+IMPORTANT NOTES:
+* This version uses a new configuration structure.  You *MUST* run the
+  included vconf2dir program.  The RPM tries to do this automatically.
+-------------------------------------------------------------------------------
+Changes in version 0.92.2
+
+Bug Fixes:
+- Delivery to partially qualified aliases was broken again in a few hard
+  to trace cases by potentially changing one character in the domain
+  address.  Fixed by rewriting the envelope building code into something
+  simpler and more efficient.
+-------------------------------------------------------------------------------
+Changes in version 0.92.1
+
+Bug Fixes:
+- Delivery to partially qualified aliases (such as the common 'root@')
+  caused vdeliver to either crash itself or to cause qmail-queue to
+  crash (since qmail-queue expects FQDN addresses).  This behavior has
+  been fixed to make such addresses use a domain name of the contents of
+  control/me.
+-------------------------------------------------------------------------------
+Changes in version 0.92
+
+New Features:
+- Aliases can now have passwords.  See the man page for vaddalias or the
+  CGI documentation for details on how to create such an alias.  The
+  intended effect is that, once set up, a virtual user could "own" an
+  alias, for the purpose of changing its destination (or password, of
+  course).
+
+Bug Fixes:
+- Delivery to aliases in vdeliver used to go through qmail-inject.  This
+  would cause qmail to reformat headers or even bounce the message.
+  vdeliver now sends aliases through qmail-queue, the same way that
+  qmail itself does it.
+-------------------------------------------------------------------------------
+Changes in version 0.91
+
+New Features:
+- Command-line and CGI programs to change an alias (to avoid the delete,
+  recreate cycle).
+
+Bug Fixes:
+- Always set the mode on created files to be read-write-only by owner.
+
+Other Changes:
+- vdeliver now uses fdbuf instead of raw I/O to deliver content.
+- Changed the default default username from '*' to '+', to avoid
+  confusion when typing '*' at a shell prompt.
+- Command-line tools now count and report the number of errors
+  encountered and exit false if any errors occurred.
+-------------------------------------------------------------------------------
+Changes in version 0.90.2
+
+New Features: None
+
+Bug Fixes:
+- Fixed compile problem on systems lacking the O_SYNC definition.
+- Fixed compile problem on systems where perror is in stdio.h, and
+  stdio.h is not included through other includes.
+
+NOTES: If you did not have a problem compiling 0.90 or 0.90.1, don't
+bother with this version.
+-------------------------------------------------------------------------------
+Changes in version 0.90.1
+
+New Features: None
+
+Bug Fixes:
+- Added definitions for MIN and MAX in md5-crypt.c if they aren't
+  defined by the included headers.
+- Removed the include of errnos.h in vpwentry_putpw.cc
+
+NOTES: If you did not have a problem compiling 0.90, don't bother with
+this version.
+-------------------------------------------------------------------------------
+Changes in version 0.90
+
+New Features:
+- Eliminated all dependance on any C++ library by incorporating my own
+  C++ I/O library.
+- Dropped the RSA MD5 library and incorporated the GNU MD5 code.
+- Added the GNU md5-crypt module which should provide compatibility with
+  all systems that do MD5-based passcodes.  The new code will read in
+  and authenticate against standard DES-crypted codes, the new standard
+  MD5-crypted '$1$' style codes, and my mistaken MD5 hashes (for
+  temporary backwards compatibility), and will write out the '$1$' style
+  MD5 codes.
+
+Bug Fixes:
+- Fixed a nearly invisible bug in the parsing of the configuration file
+  (it was too lenient in the syntax it allowed).
+- In the bulletin code, the timestamp file was named wrong
+  ("maildir/cur/.timestamp" instead of "maildir/.timestamp"), and it was
+  not created with a proper mode flag.
+
+Other Changes:
+- This package is now distributed under the GPL.
+- The daemon will now not print out any "Accepted Connection" messages
+  unless the verbose flag is set.
+- Inverted the sense of the crypt flag in configure.  There is now a
+  "--enable-crypt" flag which causes the code to revert to only using
+  crypt for password encryption and comparison (the default is to use
+  the built-in md5-crypt module).
+
+NOTES:
+- My plan to move from a fork-based daemon to a thread-based one is on
+  temporary hold until I can complete several other more important
+  reorganizations and cleanups, most importantly completing a generic DB
+  interface layer.
+-------------------------------------------------------------------------------
+Changes in version 0.89
+
+New Features:
+- Changed the file format for the virtual password tables to using CDB
+  tables.
+- The daemon now forks immediately after accepting a connection,
+  allowing for greater concurrency in the POP3 server.
+
+Bug Fixes:
+- Use a ".timestamp" file in a virtual user's maildir to determine the
+  last login time for bulletin delivery.
+
+Other Changes:
+- Removed all the cache tables in the daemon.
+- Did a major reorganization of the libraries and header files.
+
+IMPORTANT NOTES:
+* This package now uses an incompatible file format for the virtual
+  domain password tables.  You *MUST* run "vpasswd2cdb" in each
+  domain to convert your tables before starting the new daemon!
+-------------------------------------------------------------------------------
+Changes in version 0.88
+
+New Features:
+- Long passwords are now supported using MD5 hashing to create the
+  encoded version.  The code will still read the older passwords but
+  will always write out MD5 hashes.
+
+Bug Fixes:  None
+
+Other Changes:
+- I am now finally using automake to build the package.
+-------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,14 @@
+vmailmgr
+version 0.96.9
+2000-09-30
+Bruce Guenter <bruceg@em.ca>
+
+Vmailmgr provides a virtualizing password-checking interface to
+qmail-pop3d and courier IMAP as well as both a delivery agent to
+automatically deliver mail within a virtual domain and a set of tools
+to manage such a domain from either the command line or from the web.
+
+This program is Copyright(C) 2000 Bruce Guenter, and may be copied
+according to the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 or a later
+version.  A copy of this license is included with this package.  This
+package comes with no warranty of any kind.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TODO	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,130 @@
+Here are the things that I have left to complete (roughly in order of
+personal preference).  The lines marked "RELEASE TARGET" are the point
+of development that I hope to reach before I make another release.  Some
+of the other items after the last "RELEASE TARGET" may make it into a
+release if I feel like it.  I want short and easy to define goals so I
+can keep the development periods shorter.
+
+- Add note to FAQ regarding PHP error code 255 meaning the daemon is not
+  running properly (once it's been confirmed).
+
+- Add tests for:
+  - authvmailmgr
+  - execution of presetuid and postsetuid hooks in authvmailmgr
+
+- Add note to FAQ or HOWTO regarding the two interfaces
+
+- Fix checkvpw to set MAILDIR before executing postsetuid somehow
+
+- Convert existing TeXinfo documentation to SGML
+
+- Add a mailbox size daemon command
+
+- Expand the record format to include a "last modified" field, and to
+  change the flag values from binary 0/1 to ASCII.
+
+- Add the necessary code for NDBM, MySQL, and PostgreSQL password tables.
+
+- Add more complete tests to verify correct operation of "vaddusers"
+  command.
+
+- Add Courier IMAP support to the bulletin facility
+
+- Add support to the vpwtable template that allows writing a batch of
+  users in a more efficient manner
+  - start writing (locks the table for other writes, enter nosync mode)
+  - append record (check for prior existance of record, add it)
+  - stop writing (sync data and unlock the table)
+
+- Use the above to support a more efficient version of:
+  - vpasswd2db
+  - vrehash
+
+- Figure out how to make vdeliver write to both the output file and the
+  queue simultaneously, to avoid needing to do rewinds.
+
+RELEASE TARGET 0.97
+
+- Make the daemon commands stand-alone modules, using the revised daemon
+  communication protocol.  The daemon then just forks, reads in the
+  command name, validates it, and hands off to an authentication module.
+
+- The authentication module checks for a custom authentication type
+  based on the command name, does authentication, does setuid,chdir,
+  and executes the actual command.
+
+RELEASE TARGET 1.00
+
+- Set up the necessary structures to completely seperate the virtual
+  domain information and the real user information, such that each user
+  can have a list of virtual domains assigned to it.  This structure
+  will specify:
+  - a domain prefix
+  - a directory
+  In this way, the virtualdomains will contain:
+    domain.org:username-prefix
+  And the domain listing with list
+    prefix:subdirectory
+  Each domain will have a completely independant user directory and
+  password table.
+
+RELEASE TARGET 1.XX
+
+- Bug fixes and clean-ups, and documentation improvements
+
+RELEASE TARGET 2.00
+
+- Investigate making all virtual users have a directory
+
+- add a "vadddomain" command that:
+  - adds a new user to /etc/passwd
+  - creates the new user directory
+  - su's to that user and runs vsetup
+  - fixes the user's home directory permissions
+  - adds entries to control/virtualdomains
+  - adds entries to control/rcpthosts
+
+- dynamic information per mailbox:
+  - total number of emails and bytes received
+  - number of emails and bytes currently
+  - time of first and last messages
+  - last access time via POP3
+  - text file named "data"
+  - one line per datum, using "key=value" format
+
+- Write library routines, interfaced through vpwentry, that can
+  get/set the dynamic data.
+
+- Modifiy the pop bulletin command to take the bulletin directory on the
+  command line?
+
+- Continue to seperate the "misc" library directory into modules.
+
+- Add a daemon command to list all the configuration for a virtual
+  domain.
+
+- document vchattr, vchforwards
+
+- limit the number of accounts created per virtual domain
+
+- look into interoperating with sqwebmail http://www.inter7.com/sqwebmail/
+
+- look into interoperating with qmailadmin http://www.inter7.com/qmailadmin/
+
+- add support for a streaming protocol, such that multiple commands
+  could be issued per daemon session
+
+- in all the command-line programs:
+  - if the environment variable VDOMAIN is set, read the virtual domain
+    from that variable, prompt for a password, and do a server call
+
+- In vmailmgrd:
+  ? add support for PAM for non-virtual users (this may be difficult,
+    requiring a change in the authentication model)
+
+- documentation
+  - write a "getting started" guide
+
+- miscelaneous
+  - code clean-ups, including internal documentation
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/acconfig.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,16 @@
+/* Package name */
+#undef PACKAGE
+
+/* Version number */
+#undef VERSION
+
+#undef BINDIR
+
+/* Use only crypt(3) for password encryption */
+#undef USE_CRYPT
+
+/* Use Kerberos 5 authentication */
+#undef USE_KRB5
+
+#undef VPWTABLE_CDB
+#undef VPWTABLE_GDBM
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/acinclude.m4	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,30 @@
+dnl TRY_CXX_FLAG(FLAG,[ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
+AC_DEFUN(TRY_CXX_FLAG,
+[echo >conftest.cc
+if ${CXX-g++} ${CXXFLAGS} -c [$1] conftest.cc >/dev/null 2>&1; then
+  ifelse([$2], , :, [rm -f conftest*
+  $2])
+else
+  ifelse([$3], , :, [rm -f conftest*
+  $3])
+fi
+rm -f conftest*])
+
+AC_DEFUN(CXX_NO_RTTI,
+[AC_CACHE_CHECK(whether ${CXX-g++} accepts -fno-rtti,
+	local_cv_flag_NO_RTTI,
+	TRY_CXX_FLAG(-fno-rtti,
+		local_cv_flag_NO_RTTI=yes,
+		local_cv_flag_NO_RTTI=no))
+test "$local_cv_flag_NO_RTTI" = yes && CXXFLAGS="$CXXFLAGS -fno-rtti"
+])
+
+AC_DEFUN(CXX_NO_EXCEPTIONS,
+[AC_CACHE_CHECK(whether ${CXX-g++} accepts -fno-exceptions,
+	local_cv_flag_NO_EXCEPTIONS,
+	TRY_CXX_FLAG(-fno-exceptions,
+		local_cv_flag_NO_EXCEPTIONS=yes,
+		local_cv_flag_NO_EXCEPTIONS=no))
+test "$local_cv_flag_NO_EXCEPTIONS" = yes && CXXFLAGS="$CXXFLAGS -fno-exceptions"
+])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aclocal.m4	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,173 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4a
+
+dnl Copyright (C) 1994, 1995-8, 1999 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.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+dnl TRY_CXX_FLAG(FLAG,[ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
+AC_DEFUN(TRY_CXX_FLAG,
+[echo >conftest.cc
+if ${CXX-g++} ${CXXFLAGS} -c [$1] conftest.cc >/dev/null 2>&1; then
+  ifelse([$2], , :, [rm -f conftest*
+  $2])
+else
+  ifelse([$3], , :, [rm -f conftest*
+  $3])
+fi
+rm -f conftest*])
+
+AC_DEFUN(CXX_NO_RTTI,
+[AC_CACHE_CHECK(whether ${CXX-g++} accepts -fno-rtti,
+	local_cv_flag_NO_RTTI,
+	TRY_CXX_FLAG(-fno-rtti,
+		local_cv_flag_NO_RTTI=yes,
+		local_cv_flag_NO_RTTI=no))
+test "$local_cv_flag_NO_RTTI" = yes && CXXFLAGS="$CXXFLAGS -fno-rtti"
+])
+
+AC_DEFUN(CXX_NO_EXCEPTIONS,
+[AC_CACHE_CHECK(whether ${CXX-g++} accepts -fno-exceptions,
+	local_cv_flag_NO_EXCEPTIONS,
+	TRY_CXX_FLAG(-fno-exceptions,
+		local_cv_flag_NO_EXCEPTIONS=yes,
+		local_cv_flag_NO_EXCEPTIONS=no))
+test "$local_cv_flag_NO_EXCEPTIONS" = yes && CXXFLAGS="$CXXFLAGS -fno-exceptions"
+])
+
+
+# Do all the work for Automake.  This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+dnl We require 2.13 because we rely on SHELL being computed by configure.
+AC_PREREQ([2.13])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+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(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "[$]*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "[$]*" != "X $srcdir/configure conftestfile" \
+      && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "[$]2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+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.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+   $1=$2
+   AC_MSG_RESULT(found)
+else
+   $1="$3/missing $2"
+   AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+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.
+dnl This file resides in the same directory as the config header
+dnl that is generated.  We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+  case " <<$>>CONFIG_HEADERS " in
+  *" <<$>>am_file "*<<)>>
+    echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+    ;;
+  esac
+  am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,33 @@
+bin_PROGRAMS = checkvpw vauthenticate
+authlib_PROGRAMS = authvmailmgr
+authlibdir = ${prefix}/lib/courier-imap/libexec/authlib/
+
+noinst_PODS = checkvpw.pod vauthenticate.pod
+noinst_HTMLS = $(noinst_PODS:.pod=.html)
+man_MANS = $(noinst_PODS:.pod=.1)
+
+CLEANFILES = $(man_MANS) $(noinst_HTMLS) \
+	pod2html-dircache pod2html-itemcache
+EXTRA_DIST = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS)
+
+all: docs
+
+docs: $(noinst_HTMLS) $(man_MANS)
+
+dist-hook:
+	touch $(distdir)/*.html $(distdir)/*.[123456789]
+
+%.1: %.pod ../configure.in; $(POD2MAN) --section=1 $< >$@
+%.html: %.pod; $(POD2HTML) $< >$@
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = $(CIINCLUDES) -I../lib
+
+checkvpw_SOURCES = checkvpw.cc authvlib.cc authvlib.h
+checkvpw_LDADD = ../lib/libvmailmgr.a
+
+authvmailmgr_SOURCES = authvmailmgr.cc authvlib.cc authvlib.h
+authvmailmgr_LDADD = ../lib/libvmailmgr.a -L../lib/courier-authlib -lauthmod
+
+vauthenticate_SOURCES = vauthenticate.cc authvlib.cc authvlib.h
+vauthenticate_LDADD = ../lib/libvmailmgr.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,445 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+bin_PROGRAMS = checkvpw vauthenticate
+authlib_PROGRAMS = authvmailmgr
+authlibdir = ${prefix}/lib/courier-imap/libexec/authlib/
+
+noinst_PODS = checkvpw.pod vauthenticate.pod
+noinst_HTMLS = $(noinst_PODS:.pod=.html)
+man_MANS = $(noinst_PODS:.pod=.1)
+
+CLEANFILES = $(man_MANS) $(noinst_HTMLS) 	pod2html-dircache pod2html-itemcache
+
+EXTRA_DIST = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS)
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = $(CIINCLUDES) -I../lib
+
+checkvpw_SOURCES = checkvpw.cc authvlib.cc authvlib.h
+checkvpw_LDADD = ../lib/libvmailmgr.a
+
+authvmailmgr_SOURCES = authvmailmgr.cc authvlib.cc authvlib.h
+authvmailmgr_LDADD = ../lib/libvmailmgr.a -L../lib/courier-authlib -lauthmod
+
+vauthenticate_SOURCES = vauthenticate.cc authvlib.cc authvlib.h
+vauthenticate_LDADD = ../lib/libvmailmgr.a
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(authlib_PROGRAMS) $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+authvmailmgr_OBJECTS =  authvmailmgr.o authvlib.o
+authvmailmgr_DEPENDENCIES =  ../lib/libvmailmgr.a
+authvmailmgr_LDFLAGS = 
+checkvpw_OBJECTS =  checkvpw.o authvlib.o
+checkvpw_DEPENDENCIES =  ../lib/libvmailmgr.a
+checkvpw_LDFLAGS = 
+vauthenticate_OBJECTS =  vauthenticate.o authvlib.o
+vauthenticate_DEPENDENCIES =  ../lib/libvmailmgr.a
+vauthenticate_LDFLAGS = 
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(authvmailmgr_SOURCES) $(checkvpw_SOURCES) $(vauthenticate_SOURCES)
+OBJECTS = $(authvmailmgr_OBJECTS) $(checkvpw_OBJECTS) $(vauthenticate_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps authenticate/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-authlibPROGRAMS:
+
+clean-authlibPROGRAMS:
+	-test -z "$(authlib_PROGRAMS)" || rm -f $(authlib_PROGRAMS)
+
+distclean-authlibPROGRAMS:
+
+maintainer-clean-authlibPROGRAMS:
+
+install-authlibPROGRAMS: $(authlib_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(authlibdir)
+	@list='$(authlib_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "  $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(authlibdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	     $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(authlibdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-authlibPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(authlib_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(authlibdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "  $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	     $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+authvmailmgr: $(authvmailmgr_OBJECTS) $(authvmailmgr_DEPENDENCIES)
+	@rm -f authvmailmgr
+	$(CXXLINK) $(authvmailmgr_LDFLAGS) $(authvmailmgr_OBJECTS) $(authvmailmgr_LDADD) $(LIBS)
+
+checkvpw: $(checkvpw_OBJECTS) $(checkvpw_DEPENDENCIES)
+	@rm -f checkvpw
+	$(CXXLINK) $(checkvpw_LDFLAGS) $(checkvpw_OBJECTS) $(checkvpw_LDADD) $(LIBS)
+
+vauthenticate: $(vauthenticate_OBJECTS) $(vauthenticate_DEPENDENCIES)
+	@rm -f vauthenticate
+	$(CXXLINK) $(vauthenticate_LDFLAGS) $(vauthenticate_OBJECTS) $(vauthenticate_LDADD) $(LIBS)
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+install-man1:
+	$(mkinstalldirs) $(DESTDIR)$(man1dir)
+	@list='$(man1_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+	  $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+	done
+
+uninstall-man1:
+	@list='$(man1_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+	  rm -f $(DESTDIR)$(man1dir)/$$inst; \
+	done
+install-man: $(MANS)
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+	@$(NORMAL_UNINSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = authenticate
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+authvlib.o: authvlib.cc ../config.h ../lib/ac/time.h authvlib.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/pwentry.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/misc/exec.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/lookup.h \
+	../lib/vdomain/vdomain.h ../lib/vpwtable/vpwtable.h \
+	../lib/misc/response.h
+authvmailmgr.o: authvmailmgr.cc ../config.h ../lib/misc/exec.h \
+	../lib/vpwentry/vpwentry.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/strlist.h authvlib.h \
+	../lib/misc/pwentry.h ../lib/config/configrc.h \
+	../lib/courier-authlib/auth.h ../lib/courier-authlib/authmod.h
+checkvpw.o: checkvpw.cc ../config.h ../lib/config/configrc.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/strlist.h ../lib/misc/exec.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/stat_fns.h authvlib.h \
+	../lib/misc/pwentry.h
+vauthenticate.o: vauthenticate.cc ../config.h authvlib.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/pwentry.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am: install-authlibPROGRAMS install-man
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-authlibPROGRAMS uninstall-binPROGRAMS \
+		uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(authlibdir) $(DESTDIR)$(bindir) \
+		$(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-authlibPROGRAMS mostlyclean-binPROGRAMS \
+		mostlyclean-compile mostlyclean-tags \
+		mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-authlibPROGRAMS clean-binPROGRAMS clean-compile \
+		clean-tags clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-authlibPROGRAMS distclean-binPROGRAMS \
+		distclean-compile distclean-tags distclean-generic \
+		clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-authlibPROGRAMS \
+		maintainer-clean-binPROGRAMS maintainer-clean-compile \
+		maintainer-clean-tags maintainer-clean-generic \
+		distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-authlibPROGRAMS distclean-authlibPROGRAMS \
+clean-authlibPROGRAMS maintainer-clean-authlibPROGRAMS \
+uninstall-authlibPROGRAMS install-authlibPROGRAMS \
+mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile install-man1 uninstall-man1 install-man \
+uninstall-man tags mostlyclean-tags distclean-tags clean-tags \
+maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+all: docs
+
+docs: $(noinst_HTMLS) $(man_MANS)
+
+dist-hook:
+	touch $(distdir)/*.html $(distdir)/*.[123456789]
+
+%.1: %.pod ../configure.in; $(POD2MAN) --section=1 $< >$@
+%.html: %.pod; $(POD2HTML) $< >$@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/authvlib.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,110 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include "ac/time.h"
+#include <unistd.h>
+#include "authvlib.h"
+#include "misc/exec.h"
+#include "misc/lookup.h"
+#include "vdomain/vdomain.h"
+
+#ifndef HAVE_GETHOSTNAME
+int gethostname(char *name, size_t len);
+#endif
+
+void set_domain(mystring& name, mystring& domain)
+{
+  int sep = name.find_first_of(config->separators());
+  if(sep >= 0) {
+    domain = name.right(sep+1);
+    name = name.left(sep);
+  }
+  else {
+    domain = getenv("TCPLOCALHOST");
+    if(!domain) {
+      char tmp[256];
+      if(gethostname(tmp, 256))
+	fail_temporary("Error determining local host name");
+      domain = tmp;
+    }
+  }
+  if(!name)
+    fail_login("Empty user name");
+  if(!domain)
+    fail_login("Empty domain name");
+}
+
+static vdomain* domain = 0;
+
+void set_user(const pwentry* pw)
+{
+  pw->export_env();
+  if(!!exec_presetuid && execute(exec_presetuid))
+    fail_temporary("Execution of presetuid failed");
+  if(setgid(pw->gid) == -1 ||
+     setuid(pw->uid) == -1 ||
+     chdir(pw->home.c_str()) == -1)
+    fail_temporary("Bad user data in password file");
+  domain = new vdomain(*pw);
+  config = &domain->config;
+}
+
+static user_data* check(mystring fulluser, mystring password,
+			bool virtual_only)
+{
+  mystring virtname;
+  pwentry* basepw;
+  if(!lookup_baseuser(fulluser, basepw, virtname))
+    fail_login("Invalid or unknown base user or domain");
+  presetenv("VUSER=", virtname);
+  if(!virtname) {
+    if(virtual_only)
+      return 0;
+    if(!basepw->authenticate(password))
+      fail_login("Invalid or incorrect password");
+    set_user(basepw);
+    return new user_data(basepw, "", "");
+  }
+  else {
+    set_user(basepw);
+    vpwentry* vpw = domain->lookup(virtname, true);
+    if(!vpw || !vpw->mailbox)
+      fail_login("Invalid or unknown virtual user");
+    if(!vpw->authenticate(password))
+      fail_login("Invalid or incorrect password");
+    if(vpw->expiry < (unsigned)time(0))
+      fail_login("Account has expired");
+    vpw->export_env();
+    return new user_data(basepw, vpw->mailbox, vpw->name);
+  }
+}
+
+user_data* authenticate(mystring name, mystring pass, mystring domain,
+			bool virtual_only)
+{
+  mystring baseuser;
+  if(!is_local(domain)) {
+    mystring baseuser = find_virtual(domain);
+    if(!!baseuser)
+      name = baseuser + "-" + name;
+  }
+  user_data* result = check(name, pass, virtual_only);
+  if(result && !!exec_postsetuid && execute(exec_postsetuid))
+    fail_temporary("Execution of presetuid failed");
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/authvlib.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,40 @@
+#ifndef VMAILMGR__VMAILMGR_AUTH_LIBRARY__H__
+#define VMAILMGR__VMAILMGR_AUTH_LIBRARY__H__
+
+#include "mystring/mystring.h"
+#include "misc/pwentry.h"
+
+struct user_data
+{
+  uid_t uid;
+  gid_t gid;
+  mystring name;
+  mystring home;
+  mystring maildir;
+  mystring vname;
+  
+  user_data(pwentry* pw, mystring md, mystring v)
+    : uid(pw->uid), gid(pw->gid), name(pw->name), home(pw->home),
+      maildir(md), vname(v)
+  {
+  }
+  
+  ~user_data() { }
+
+  bool non_virtual() const { return !vname; }
+};
+
+// The following routines are defined in authvlib.cc
+void set_domain(mystring& name, mystring& domain);
+user_data* authenticate(mystring name, mystring pass, mystring domain,
+			bool virtual_only = false);
+void set_user(const pwentry* pw);
+
+// The following must be defined by the authentication module.
+extern const mystring exec_presetuid;
+extern const mystring exec_postsetuid;
+extern void fail_login(const char* msg);
+extern void fail_baddata(const char* msg);
+extern void fail_temporary(const char* msg);
+
+#endif // VMAILMGR__VMAILMGR_AUTH_LIBRARY__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/authvmailmgr.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,107 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "misc/exec.h"
+#include "authvlib.h"
+// Courier-IMAP includes
+#include "courier-authlib/auth.h"
+#include "courier-authlib/authmod.h"
+
+static mystring username;
+static mystring passcode;
+static mystring domain;
+static int global_argc;
+static char** global_argv;
+
+const mystring exec_presetuid = "authvmailmgr-presetuid";
+const mystring exec_postsetuid = "authvmailmgr-postsetuid";
+
+void fail(const char* msg, const char* execfile)
+{
+  presetenv("AUTHVMAILMGR_ERROR=", msg);
+  execute(execfile);
+}
+
+void fail_login(const char* msg)
+{
+  fail(msg, "authvmailmgr-loginfail");
+  authmod_fail_completely();
+}
+
+void fail_baddata(const char* msg)
+{
+  fail(msg, "authvmailmgr-error");
+  authmod_fail_completely();
+}
+
+void fail_temporary(const char* msg)
+{
+  fail(msg, "authvmailmgr-error");
+  authmod_fail_completely();
+}
+
+static void parse_data(const char* /*service*/, const char* authtype,
+		       const char* authdata, int /*issession*/)
+{
+  mystring_iter iter(authdata, '\n');
+  username = *iter;
+  ++iter;
+  passcode = *iter;
+
+  if(strcmp(authtype, AUTHTYPE_LOGIN))
+    fail_temporary("Invalid authentication type, must be 'login'");
+  if(!username || !passcode)
+    fail_baddata("Invalid authentication data");
+
+  set_domain(username, domain);
+}
+
+void auth_vmailmgr()
+{
+  user_data* udata = authenticate(username, passcode, domain, true);
+  if(!udata)
+    // This point is only reached if the domain is not virtual, in which
+    // case we pass the authentication on to the next module.
+    authmod_fail(global_argc, global_argv);
+
+  if(execute("authvmailmgr-presetuid"))
+    fail_temporary("Execution of authvmailmgr-presetuid failed");
+  
+  // authsuccess() set ups the environment, CWD, and GID/UID
+  authsuccess(udata->home.c_str(), 0, &udata->uid, &udata->gid,
+	      username.c_str(), 0);
+  presetenv("MAILDIR=", udata->maildir);
+
+  if(execute("authvmailmgr-postsetuid"))
+    fail_temporary("Execution of authvmailmgr-postsetuid failed");
+}
+
+int main(int argc, char **argv)
+{
+  global_argc = argc;
+  global_argv = argv;
+  
+  const char *service, *type;
+  char *authdata;
+
+  authmod_init(argc, argv, &service, &type, &authdata);
+  parse_data(service, type, authdata, 1);
+  auth_vmailmgr();
+  authmod_success(argc, argv, username.c_str());
+  return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/checkvpw.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,291 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH CHECKVPW 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+checkvpw \- check passwords for virtual and non-virtual users
+.SH "SYNOPSIS"
+\fBcheckvpw\fR \fBsubprogram\fR [\fBarguments...\fR]
+.SH "DESCRIPTION"
+This program is a drop-in replacement for the standard checkpassword,
+written by D. J. Bernstein (djb@pobox.com).
+In the absence of virtual hosting (determined by the use of
+\fI/var/qmail/control/virtualdomainss\fR and IP aliases),
+it behaves identically to checkpassword.
+When virtual hosting is used, it permits logins from a unique set of
+users for each of the aliases.
+.PP
+\fIcheckvpw\fR must be run from either the \fItcp-env\fR program
+(part of the \fIqmail\fR
+package) or from a suitable substitute, such as \fItcpserver\fR
+(part of the \fIucspi-tcp\fR package).
+These packages are used to determine to
+which address a remote host is connecting.
+\fIcheckvpw\fR must also be passed the checkpassword-compatible
+authentication data on file descriptor three.
+This can be accomplished by running it from a tool such as
+\fIqmail-popup\fR.
+.PP
+\fIcheckvpw\fR accepts a command line in the following format:
+.PP
+.Vb 1
+\&        checkvpw [subprogram] [arguments...]
+.Ve
+If the authentication information is valid, the subprogram is run,
+otherwise \fIcheckvpw\fR returns an error to the program that invokes it.
+.PP
+If the user name contains the character \f(CW@\fR, the host name
+reported by \fItcp-env\fR is replaced by the string following the
+\f(CW@\fR, and the user name is replaced by the string preceding the
+\f(CW@\fR.
+If the local host name reported by \fItcp-env\fR matches one of those
+in \fI/var/qmail/control/virtualdomains\fR, \fIcheckvpw\fR prepends the
+\fIprepend\fR string associated with the host name to the given user
+name.
+Wildcards in \fIvirtualdomains\fR are permitted and are handled in the
+same way \fIqmail\fR handles them (see the \fIqmail-send\fR manpage).
+For example, if the line \f(CW.bar.com:bar\fR appears in the virtual hosts
+file, it matches \f(CWone.two.bar.com\fR but not \f(CWbar.com\fR.
+.PP
+If the user name resulting from the above step appears in the system
+password file (typically \fI/etc/passwd\fR), the user is treated as a
+local user and authenticated with the information from that file.
+If this authentication succeeds, the mail directory is set to the
+subdirectory named on the command line.
+If the user name does not appear in the system password file and is of
+the form \f(CWname-ext\fR where \f(CWname\fR does appear in the password
+file, the user is treated as a \*(L"virtual\*(R" user and authenticated with the
+information from a file named \fIpasswd\fR in the user's home directory.
+If this authentication succeeds, the mail directory is set to the
+subdirectory \fIusers/ext/\fR in the user's home directory, where
+\f(CWext\fR is from the above step.
+.PP
+\fIcheckvpw\fR also does some rewriting on the arguments of the
+subprogram.
+Any argument matching the string \*(L"\f(CWmaildir\fR\*(R" (ignoring case) is
+replaced with the full path of the mail directory, as determined by the
+steps above.
+.PP
+This program may be invoked in combination with \fIqmail-popup\fR and
+\fIqmail-pop3d\fR from inetd by placing the following line in the
+\fI/etc/inetd.conf\fR configuration file (all one line):
+.PP
+.Vb 1
+\&        pop-3 stream tcp nowait root /var/qmail/bin/tcp-env tcp-env -R /var/qmail/bin/qmail-popup <hostname> /usr/bin/checkvpw /var/qmail/bin/qmail-pop3d Maildir/
+.Ve
+.SH "RETURN VALUE"
+0 if the user is successfully authenticated, nonzero if any error
+occurred.  Exit code 1 indicates that a bad password was given, 2
+indicates that the program was used incorrectly, and 111 indicates
+a temporary failure.
+.SH "ENVIRONMENT"
+\fIcheckvpw\fR requires that \f(CWTCPLOCALHOST\fR be set to the host name of
+the local address of the connection.
+.SH "SEE ALSO"
+\fIvdeliver\fR\|(1)
+.SH "AUTHOR"
+Bruce Guenter <\fIbruceg@em.ca\fR>.
+
+.rn }` ''
+.IX Title "CHECKVPW 1"
+.IX Name "checkvpw - check passwords for virtual and non-virtual users"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "ENVIRONMENT"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHOR"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/checkvpw.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,158 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include "config/configrc.h"
+#include "misc/exec.h"
+#include "misc/stat_fns.h"
+#include "authvlib.h"
+
+const mystring exec_presetuid = "checkvpw-presetuid";
+const mystring exec_postsetuid = "checkvpw-postsetuid";
+
+void fail(const char* msg, const char* execfile, int code)
+{
+  presetenv("CHECKVPW_ERROR=", msg);
+  execute(execfile);
+  exit(code);
+}
+
+void fail_login(const char* msg)
+{
+  fail(msg, "checkvpw-loginfail", 1);
+}
+
+void fail_baddata(const char* msg)
+{
+  fail(msg, "checkvpw-error", 2);
+}
+
+void fail_temporary(const char* msg)
+{
+  fail(msg, "checkvpw-error", 111);
+}
+
+struct auth_data 
+{
+  mystring name;
+  mystring pass;
+  mystring stamp;
+
+  auth_data(mystring n, mystring p, mystring s)
+    : name(n), pass(p), stamp(s)
+  {
+    name = name.lower();
+  }
+  ~auth_data() { }
+};
+
+auth_data* getdata()
+{
+  char buf[513];
+  unsigned buflen = 0;
+  while(buflen < sizeof(buf)) {
+    int r;
+    do
+      r = read(3, buf+buflen, sizeof(buf) - buflen);
+    while ((r == -1) && (errno == EINTR));
+    if (r == -1) fail_baddata("Read error");
+    if (r == 0) break;
+    buflen += r;
+  }
+  if(buflen >= sizeof(buf))
+    fail_baddata("Read buffer too long");
+
+  char *name = buf;
+  char *pass = 0;
+  char *stamp = 0;
+  bool has_end = false;
+  
+  char* bufend = buf+sizeof(buf);
+
+  for(char* ptr = buf; ptr < bufend; ptr++)
+    if(*ptr == 0) {
+      ++ptr;
+      if(!pass)
+	pass = ptr;
+      else if(!stamp)
+	stamp = ptr;
+      else {
+	has_end = true;
+	break;
+      }
+    }
+  if(!has_end)
+    fail_baddata("Invalid data");
+  
+  close(3);
+  return new auth_data(name, pass, stamp);
+}
+
+char* strcasestr(const char* haystack, const char* needle)
+{
+  for(size_t hlength = strlen(haystack), nlength = strlen(needle);
+      hlength >= nlength; hlength--, haystack++)
+    if(!strncasecmp(haystack, needle, nlength))
+      return (char*)haystack;
+  return 0;
+}
+
+unsigned find_maildir(int argc, const char* args[])
+{
+  for(int arg = 0; arg < argc; arg++) {
+    if(strcasestr(args[arg], config->maildir_arg_str().c_str()))
+      return arg;
+  }
+  return argc-1;
+}
+
+void set_maildirarg(int argc, const char* argv[], user_data* udata)
+{
+  unsigned maildirarg = find_maildir(argc-1, argv+1) + 1;
+  if(!udata->maildir)
+    udata->maildir = argv[maildirarg];
+  if(!is_dir(udata->maildir.c_str()))
+    udata->maildir = config->error_maildir();
+  presetenv("MAILDIR=", udata->maildir);
+
+  char* str = new char[udata->maildir.length()+1];
+  memcpy(str, udata->maildir.c_str(), udata->maildir.length()+1);
+  argv[maildirarg] = str;
+}
+
+int main(int argc, const char* argv[])
+{
+  if(argc <= 1)
+    fail_baddata("No subprogram given to execute");
+  
+  auth_data* auth = getdata();
+
+  mystring hostname;
+  set_domain(auth->name, hostname);
+
+  user_data* udata = authenticate(auth->name, auth->pass, hostname);
+
+  set_maildirarg(argc, argv, udata);
+  
+  if(execute_one(argv+1))
+    fail_temporary("Execution of command line arguments failed");
+
+  execute("checkvpw-postexec");
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/checkvpw.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,125 @@
+<HTML>
+<HEAD>
+<TITLE>checkvpw - check passwords for virtual and non-virtual users</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#ENVIRONMENT">ENVIRONMENT</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+checkvpw - check passwords for virtual and non-virtual users
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>checkvpw</STRONG>  <STRONG>subprogram</STRONG> [<STRONG>arguments...</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program is a drop-in replacement for the standard checkpassword,
+written by D. J. Bernstein (<A
+HREF="mailto:djb@pobox.com">djb@pobox.com</A>) In the absence of virtual
+hosting (determined by the use of
+<EM>/var/qmail/control/virtualdomainss</EM> and IP aliases), it behaves identically to checkpassword. When virtual
+hosting is used, it permits logins from a unique set of users for each of
+the aliases.
+
+<P>
+<EM>checkvpw</EM> must be run from either the <EM>tcp-env</EM> program (part of the <EM>qmail</EM>
+package) or from a suitable substitute, such as <EM>tcpserver</EM>
+(part of the <EM>ucspi-tcp</EM> package). These packages are used to determine to which address a remote
+host is connecting.
+<EM>checkvpw</EM> must also be passed the checkpassword-compatible authentication data on
+file descriptor three. This can be accomplished by running it from a tool
+such as
+<EM>qmail-popup</EM>.
+
+<P>
+<EM>checkvpw</EM> accepts a command line in the following format:
+
+<P>
+<PRE>        checkvpw [subprogram] [arguments...]
+</PRE>
+<P>
+If the authentication information is valid, the subprogram is run,
+otherwise <EM>checkvpw</EM> returns an error to the program that invokes it.
+
+<P>
+If the user name contains the character <CODE>@</CODE>, the host name reported by <EM>tcp-env</EM> is replaced by the string following the
+<CODE>@</CODE>, and the user name is replaced by the string preceding the
+<CODE>@</CODE>. If the local host name reported by <EM>tcp-env</EM> matches one of those in <EM>/var/qmail/control/virtualdomains</EM>, <EM>checkvpw</EM> prepends the
+<EM>prepend</EM> string associated with the host name to the given user name. Wildcards in <EM>virtualdomains</EM> are permitted and are handled in the same way <EM>qmail</EM> handles them (see <EM>qmail-send</EM>). For example, if the line <CODE>.bar.com:bar</CODE> appears in the virtual hosts file, it matches <CODE>one.two.bar.com</CODE> but not <CODE>bar.com</CODE>.
+
+<P>
+If the user name resulting from the above step appears in the system
+password file (typically <EM>/etc/passwd</EM>), the user is treated as a local user and authenticated with the
+information from that file. If this authentication succeeds, the mail
+directory is set to the subdirectory named on the command line. If the user
+name does not appear in the system password file and is of the form <CODE>name-ext</CODE> where <CODE>name</CODE> does appear in the password file, the user is treated as a ``virtual'' user
+and authenticated with the information from a file named <EM>passwd</EM> in the user's home directory. If this authentication succeeds, the mail
+directory is set to the subdirectory <EM>users/ext/</EM> in the user's home directory, where
+<CODE>ext</CODE> is from the above step.
+
+<P>
+<EM>checkvpw</EM> also does some rewriting on the arguments of the subprogram. Any argument
+matching the string ``<CODE>maildir</CODE>'' (ignoring case) is replaced with the full path of the mail directory, as
+determined by the steps above.
+
+<P>
+This program may be invoked in combination with <EM>qmail-popup</EM> and
+<EM>qmail-pop3d</EM> from inetd by placing the following line in the
+<EM>/etc/inetd.conf</EM> configuration file (all one line):
+
+<P>
+<PRE>        pop-3 stream tcp nowait root /var/qmail/bin/tcp-env tcp-env -R /var/qmail/bin/qmail-popup &lt;hostname&gt; /usr/bin/checkvpw /var/qmail/bin/qmail-pop3d Maildir/
+</PRE>
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+0 if the user is successfully authenticated, nonzero if any error occurred.
+Exit code 1 indicates that a bad password was given, 2 indicates that the
+program was used incorrectly, and 111 indicates a temporary failure.
+
+<P>
+<HR>
+<H1><A NAME="ENVIRONMENT">ENVIRONMENT</A></H1>
+<P>
+<EM>checkvpw</EM> requires that <CODE>TCPLOCALHOST</CODE> be set to the host name of the local address of the connection.
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vdeliver(1)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR</A></H1>
+<P>
+Bruce Guenter &lt;<EM>bruceg@em.ca</EM>&gt;.
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/checkvpw.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,94 @@
+=head1 NAME
+
+checkvpw - check passwords for virtual and non-virtual users
+
+=head1 SYNOPSIS
+
+B<checkvpw> B<subprogram> [B<arguments...>]
+
+=head1 DESCRIPTION
+
+This program is a drop-in replacement for the standard checkpassword,
+written by D. J. Bernstein (djb@pobox.com).
+In the absence of virtual hosting (determined by the use of
+F</var/qmail/control/virtualdomainss> and IP aliases),
+it behaves identically to checkpassword.
+When virtual hosting is used, it permits logins from a unique set of
+users for each of the aliases.
+
+F<checkvpw> must be run from either the F<tcp-env> program
+(part of the F<qmail>
+package) or from a suitable substitute, such as F<tcpserver>
+(part of the F<ucspi-tcp> package).
+These packages are used to determine to
+which address a remote host is connecting.
+F<checkvpw> must also be passed the checkpassword-compatible
+authentication data on file descriptor three.
+This can be accomplished by running it from a tool such as
+F<qmail-popup>.
+
+F<checkvpw> accepts a command line in the following format:
+
+	checkvpw [subprogram] [arguments...]
+
+If the authentication information is valid, the subprogram is run,
+otherwise F<checkvpw> returns an error to the program that invokes it.
+
+If the user name contains the character C<@>, the host name
+reported by F<tcp-env> is replaced by the string following the
+C<@>, and the user name is replaced by the string preceding the
+C<@>.
+If the local host name reported by F<tcp-env> matches one of those
+in F</var/qmail/control/virtualdomains>, F<checkvpw> prepends the
+I<prepend> string associated with the host name to the given user
+name.
+Wildcards in F<virtualdomains> are permitted and are handled in the
+same way F<qmail> handles them (see L<qmail-send>).
+For example, if the line C<.bar.com:bar> appears in the virtual hosts
+file, it matches C<one.two.bar.com> but not C<bar.com>.
+
+If the user name resulting from the above step appears in the system
+password file (typically F</etc/passwd>), the user is treated as a
+local user and authenticated with the information from that file.
+If this authentication succeeds, the mail directory is set to the
+subdirectory named on the command line.
+If the user name does not appear in the system password file and is of
+the form C<name-ext> where C<name> does appear in the password
+file, the user is treated as a "virtual" user and authenticated with the
+information from a file named F<passwd> in the user's home directory.
+If this authentication succeeds, the mail directory is set to the
+subdirectory F<users/ext/> in the user's home directory, where
+C<ext> is from the above step.
+
+F<checkvpw> also does some rewriting on the arguments of the
+subprogram.
+Any argument matching the string "C<maildir>" (ignoring case) is
+replaced with the full path of the mail directory, as determined by the
+steps above.
+
+This program may be invoked in combination with F<qmail-popup> and
+F<qmail-pop3d> from inetd by placing the following line in the
+F</etc/inetd.conf> configuration file (all one line):
+
+	pop-3 stream tcp nowait root /var/qmail/bin/tcp-env tcp-env -R /var/qmail/bin/qmail-popup <hostname> /usr/bin/checkvpw /var/qmail/bin/qmail-pop3d Maildir/
+
+=head1 RETURN VALUE
+
+0 if the user is successfully authenticated, nonzero if any error
+occurred.  Exit code 1 indicates that a bad password was given, 2
+indicates that the program was used incorrectly, and 111 indicates
+a temporary failure.
+
+=head1 ENVIRONMENT
+
+F<checkvpw> requires that C<TCPLOCALHOST> be set to the host name of
+the local address of the connection.
+
+=head1 SEE ALSO
+
+vdeliver(1)
+
+=head1 AUTHOR
+
+Bruce Guenter <F<bruceg@em.ca>>.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/vauthenticate.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,266 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VAUTHENTICATE 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vauthenticate \- Authenticate a virtual user
+.SH "SYNOPSIS"
+\fBvauthenticate\fR
+.SH "DESCRIPTION"
+\fIvauthenticate\fR reads a domain name, user name, and pass phrase from
+standard input, and authenticates the virtual user.  If authentication
+is successful, it prints out information about the virtual user on
+stdout
+.PP
+The domain name, user name, and pass phrase are passed to
+\fIvauthenticate\fR on standard input each seperated by a NUL byte.
+.PP
+The output consists of a series of lines containing an identifier, an
+equal sign, and the data for that identifier, terminated by a newline.
+The identifiers are:
+.Ip "\s-1UID\s0" 4
+The base user's numerical user \s-1ID\s0.
+.Ip "\s-1GID\s0" 4
+The base user's numerical group \s-1ID\s0.
+.Ip "\s-1USER\s0" 4
+The base user's name.
+.Ip "\s-1HOME\s0" 4
+The base user's home directory.
+.Ip "\s-1MAILDIR\s0" 4
+The virtual user's mailbox directory, relative to \f(CWHOME\fR.
+.Ip "\s-1VUSER\s0" 4
+The virtual user's name.
+.SH "OPTIONS"
+None
+.SH "RETURN VALUE"
+Returns 0 if authentication succeeds, and non-zero otherwise.
+.SH "SEE ALSO"
+\fIvmailmgr\fR\|(7)
+.SH "CAVEATS"
+Although the output from \fIvauthenticate\fR appears to be suitable for
+using as shell input, care must be taken to escape characters that
+would cause the shell to misbehave, such as semicolons.
+.SH "RESTRICTIONS"
+This program will not authenticate non-virtual users.
+.SH "AUTHOR"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VAUTHENTICATE 1"
+.IX Name "vauthenticate - Authenticate a virtual user"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\s-1UID\s0"
+
+.IX Item "\s-1GID\s0"
+
+.IX Item "\s-1USER\s0"
+
+.IX Item "\s-1HOME\s0"
+
+.IX Item "\s-1MAILDIR\s0"
+
+.IX Item "\s-1VUSER\s0"
+
+.IX Header "OPTIONS"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "SEE ALSO"
+
+.IX Header "CAVEATS"
+
+.IX Header "RESTRICTIONS"
+
+.IX Header "AUTHOR"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/vauthenticate.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,88 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include <unistd.h>
+#include "authvlib.h"
+#include "fdbuf/fdbuf.h"
+
+const mystring exec_presetuid = 0;
+const mystring exec_postsetuid = 0;
+
+void fail_login(const char*)
+{
+  exit(1);
+}
+
+void fail_baddata(const char*)
+{
+  exit(2);
+}
+
+void fail_temporary(const char*)
+{
+  exit(111);
+}
+
+static void getdata(mystring& domain, mystring& user, mystring& pass)
+{
+  char buf[513];
+  unsigned buflen = 0;
+  while(buflen < 512) {
+    int r;
+    do
+      r = read(0, buf+buflen, sizeof(buf) - buflen);
+    while ((r == -1) && (errno == EINTR));
+    if (r == -1) fail_baddata("Read error");
+    if (r == 0) break;
+    buflen += r;
+  }
+  if(buflen >= 512)
+    fail_baddata("Read buffer too long");
+  buf[buflen] = 0;
+
+  char* ptr = buf;
+  char* end = buf + buflen;
+  
+  domain = ptr;
+  ptr += domain.length()+1;
+  if(ptr >= end)
+    fail_baddata("Missing user name");
+  user = ptr;
+  ptr += user.length()+1;
+  if(ptr >= end)
+    fail_baddata("Missing pass phrase");
+  pass = ptr;
+}
+
+int main()
+{
+  mystring user;
+  mystring pass;
+  mystring domain;
+  getdata(domain, user, pass);
+  user_data* udata = authenticate(user, pass, domain, true);
+  if(!udata)
+    return 1;
+  fout <<
+    "UID=" << udata->uid << "\n"
+    "GID=" << udata->gid << "\n"
+    "USER=" << udata->name << "\n"
+    "HOME=" << udata->home << "\n"
+    "MAILDIR=" << udata->maildir << "\n"
+    "VUSER=" << udata->vname << "\n";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/vauthenticate.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,122 @@
+<HTML>
+<HEAD>
+<TITLE>vauthenticate - Authenticate a virtual user</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#CAVEATS">CAVEATS</A>
+	<LI><A HREF="#RESTRICTIONS">RESTRICTIONS</A>
+	<LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vauthenticate - Authenticate a virtual user
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vauthenticate</STRONG>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+<EM>vauthenticate</EM> reads a domain name, user name, and pass phrase from standard input, and
+authenticates the virtual user. If authentication is successful, it prints
+out information about the virtual user on stdout
+
+<P>
+The domain name, user name, and pass phrase are passed to
+<EM>vauthenticate</EM> on standard input each seperated by a NUL byte.
+
+<P>
+The output consists of a series of lines containing an identifier, an equal
+sign, and the data for that identifier, terminated by a newline. The
+identifiers are:
+
+<DL>
+<DT><STRONG><A NAME="item_UID">UID</A></STRONG><DD>
+<P>
+The base user's numerical user ID.
+
+<DT><STRONG><A NAME="item_GID">GID</A></STRONG><DD>
+<P>
+The base user's numerical group ID.
+
+<DT><STRONG><A NAME="item_USER">USER</A></STRONG><DD>
+<P>
+The base user's name.
+
+<DT><STRONG><A NAME="item_HOME">HOME</A></STRONG><DD>
+<P>
+The base user's home directory.
+
+<DT><STRONG><A NAME="item_MAILDIR">MAILDIR</A></STRONG><DD>
+<P>
+The virtual user's mailbox directory, relative to <A HREF="#item_HOME">HOME</A>.
+
+<DT><STRONG><A NAME="item_VUSER">VUSER</A></STRONG><DD>
+<P>
+The virtual user's name.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<P>
+None
+
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+Returns 0 if authentication succeeds, and non-zero otherwise.
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vmailmgr(7)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="CAVEATS">CAVEATS</A></H1>
+<P>
+Although the output from <EM>vauthenticate</EM> appears to be suitable for using as shell input, care must be taken to
+escape characters that would cause the shell to misbehave, such as
+semicolons.
+
+<P>
+<HR>
+<H1><A NAME="RESTRICTIONS">RESTRICTIONS</A></H1>
+<P>
+This program will not authenticate non-virtual users.
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/vauthenticate.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,75 @@
+=head1 NAME
+
+vauthenticate - Authenticate a virtual user
+
+=head1 SYNOPSIS
+
+B<vauthenticate>
+
+=head1 DESCRIPTION
+
+F<vauthenticate> reads a domain name, user name, and pass phrase from
+standard input, and authenticates the virtual user.  If authentication
+is successful, it prints out information about the virtual user on
+stdout
+
+The domain name, user name, and pass phrase are passed to
+F<vauthenticate> on standard input each seperated by a NUL byte.
+
+The output consists of a series of lines containing an identifier, an
+equal sign, and the data for that identifier, terminated by a newline.
+The identifiers are:
+
+=over 4
+
+=item UID
+
+The base user's numerical user ID.
+
+=item GID
+
+The base user's numerical group ID.
+
+=item USER
+
+The base user's name.
+
+=item HOME
+
+The base user's home directory.
+
+=item MAILDIR
+
+The virtual user's mailbox directory, relative to C<HOME>.
+
+=item VUSER
+
+The virtual user's name.
+
+=back
+
+=head1 OPTIONS
+
+None
+
+=head1 RETURN VALUE
+
+Returns 0 if authentication succeeds, and non-zero otherwise.
+
+=head1 SEE ALSO
+
+vmailmgr(7)
+
+=head1 CAVEATS
+
+Although the output from F<vauthenticate> appears to be suitable for
+using as shell input, care must be taken to escape characters that
+would cause the shell to misbehave, such as semicolons.
+
+=head1 RESTRICTIONS
+
+This program will not authenticate non-virtual users.
+
+=head1 AUTHOR
+
+Bruce Guenter <bruceg@em.ca>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,28 @@
+EXTRA_DIST = listvdomain.html vaddalias.html vadduser.html vchalias.html \
+	vchattr.html vchforwards.html vdeluser.html vpasswd.html
+cgi_PROGRAMS = vpasswd vadduser vdeluser vaddalias vchattr vchforwards \
+	listvdomain
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = -I../lib
+
+vpasswd_SOURCES = vpasswd.cc
+vpasswd_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vadduser_SOURCES = vadduser.cc
+vadduser_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vdeluser_SOURCES = vdeluser.cc
+vdeluser_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vaddalias_SOURCES = vaddalias.cc
+vaddalias_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vchattr_SOURCES = vchattr.cc
+vchattr_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vchforwards_SOURCES = vchforwards.cc
+vchforwards_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+listvdomain_SOURCES = listvdomain.cc
+listvdomain_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,417 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+EXTRA_DIST = listvdomain.html vaddalias.html vadduser.html vchalias.html 	vchattr.html vchforwards.html vdeluser.html vpasswd.html
+
+cgi_PROGRAMS = vpasswd vadduser vdeluser vaddalias vchattr vchforwards 	listvdomain
+
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = -I../lib
+
+vpasswd_SOURCES = vpasswd.cc
+vpasswd_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vadduser_SOURCES = vadduser.cc
+vadduser_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vdeluser_SOURCES = vdeluser.cc
+vdeluser_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vaddalias_SOURCES = vaddalias.cc
+vaddalias_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vchattr_SOURCES = vchattr.cc
+vchattr_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+vchforwards_SOURCES = vchforwards.cc
+vchforwards_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+
+listvdomain_SOURCES = listvdomain.cc
+listvdomain_LDADD = ../lib/libcgi.a ../lib/libvmailmgr.a
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(cgi_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+vpasswd_OBJECTS =  vpasswd.o
+vpasswd_DEPENDENCIES =  ../lib/libcgi.a ../lib/libvmailmgr.a
+vpasswd_LDFLAGS = 
+vadduser_OBJECTS =  vadduser.o
+vadduser_DEPENDENCIES =  ../lib/libcgi.a ../lib/libvmailmgr.a
+vadduser_LDFLAGS = 
+vdeluser_OBJECTS =  vdeluser.o
+vdeluser_DEPENDENCIES =  ../lib/libcgi.a ../lib/libvmailmgr.a
+vdeluser_LDFLAGS = 
+vaddalias_OBJECTS =  vaddalias.o
+vaddalias_DEPENDENCIES =  ../lib/libcgi.a ../lib/libvmailmgr.a
+vaddalias_LDFLAGS = 
+vchattr_OBJECTS =  vchattr.o
+vchattr_DEPENDENCIES =  ../lib/libcgi.a ../lib/libvmailmgr.a
+vchattr_LDFLAGS = 
+vchforwards_OBJECTS =  vchforwards.o
+vchforwards_DEPENDENCIES =  ../lib/libcgi.a ../lib/libvmailmgr.a
+vchforwards_LDFLAGS = 
+listvdomain_OBJECTS =  listvdomain.o
+listvdomain_DEPENDENCIES =  ../lib/libcgi.a ../lib/libvmailmgr.a
+listvdomain_LDFLAGS = 
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(vpasswd_SOURCES) $(vadduser_SOURCES) $(vdeluser_SOURCES) $(vaddalias_SOURCES) $(vchattr_SOURCES) $(vchforwards_SOURCES) $(listvdomain_SOURCES)
+OBJECTS = $(vpasswd_OBJECTS) $(vadduser_OBJECTS) $(vdeluser_OBJECTS) $(vaddalias_OBJECTS) $(vchattr_OBJECTS) $(vchforwards_OBJECTS) $(listvdomain_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps cgi/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-cgiPROGRAMS:
+
+clean-cgiPROGRAMS:
+	-test -z "$(cgi_PROGRAMS)" || rm -f $(cgi_PROGRAMS)
+
+distclean-cgiPROGRAMS:
+
+maintainer-clean-cgiPROGRAMS:
+
+install-cgiPROGRAMS: $(cgi_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(cgidir)
+	@list='$(cgi_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "  $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(cgidir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	     $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(cgidir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-cgiPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(cgi_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(cgidir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+vpasswd: $(vpasswd_OBJECTS) $(vpasswd_DEPENDENCIES)
+	@rm -f vpasswd
+	$(CXXLINK) $(vpasswd_LDFLAGS) $(vpasswd_OBJECTS) $(vpasswd_LDADD) $(LIBS)
+
+vadduser: $(vadduser_OBJECTS) $(vadduser_DEPENDENCIES)
+	@rm -f vadduser
+	$(CXXLINK) $(vadduser_LDFLAGS) $(vadduser_OBJECTS) $(vadduser_LDADD) $(LIBS)
+
+vdeluser: $(vdeluser_OBJECTS) $(vdeluser_DEPENDENCIES)
+	@rm -f vdeluser
+	$(CXXLINK) $(vdeluser_LDFLAGS) $(vdeluser_OBJECTS) $(vdeluser_LDADD) $(LIBS)
+
+vaddalias: $(vaddalias_OBJECTS) $(vaddalias_DEPENDENCIES)
+	@rm -f vaddalias
+	$(CXXLINK) $(vaddalias_LDFLAGS) $(vaddalias_OBJECTS) $(vaddalias_LDADD) $(LIBS)
+
+vchattr: $(vchattr_OBJECTS) $(vchattr_DEPENDENCIES)
+	@rm -f vchattr
+	$(CXXLINK) $(vchattr_LDFLAGS) $(vchattr_OBJECTS) $(vchattr_LDADD) $(LIBS)
+
+vchforwards: $(vchforwards_OBJECTS) $(vchforwards_DEPENDENCIES)
+	@rm -f vchforwards
+	$(CXXLINK) $(vchforwards_LDFLAGS) $(vchforwards_OBJECTS) $(vchforwards_LDADD) $(LIBS)
+
+listvdomain: $(listvdomain_OBJECTS) $(listvdomain_DEPENDENCIES)
+	@rm -f listvdomain
+	$(CXXLINK) $(listvdomain_LDFLAGS) $(listvdomain_OBJECTS) $(listvdomain_LDADD) $(LIBS)
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = cgi
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+listvdomain.o: listvdomain.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vpwentry/vpwentry.h \
+	../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+vaddalias.o: vaddalias.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h
+vadduser.o: vadduser.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h
+vchalias.o: vchalias.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vdomain/vdomain.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/itoa.h
+vchattr.o: vchattr.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vdomain/vdomain.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/vpwentry/vpwentry.h
+vchforwards.o: vchforwards.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vdomain/vdomain.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/itoa.h
+vdeluser.o: vdeluser.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h
+vpasswd.o: vpasswd.cc ../config.h ../lib/cgi/cgi-base.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cgi/cgi-args.h ../lib/misc/server.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vdomain/vdomain.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/itoa.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-cgiPROGRAMS
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-cgiPROGRAMS
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(cgidir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-cgiPROGRAMS mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-cgiPROGRAMS clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-cgiPROGRAMS distclean-compile distclean-tags \
+		distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-cgiPROGRAMS \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-cgiPROGRAMS distclean-cgiPROGRAMS clean-cgiPROGRAMS \
+maintainer-clean-cgiPROGRAMS uninstall-cgiPROGRAMS install-cgiPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/listvdomain.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,191 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include "cgi/cgi-base.h"
+#include "misc/server.h"
+#include "vpwentry/vpwentry.h"
+#include "fdbuf/fdbuf.h"
+
+static mystring domain;
+static mystring userlink;
+
+static mystring cell_pre;
+static mystring cell_post;
+
+static mystring p_pre;
+
+static mystring table_align;
+
+mystring do_subst(mystring link, const mystring& ref)
+{
+  int pos;
+  int start = 0;
+  unsigned advance = ref.length();
+  
+  while((pos = link.find_first('%', start)) >= 0) {
+    link = link.left(pos) + ref + link.right(pos+1);
+    start = pos + advance;
+  }
+  return link;
+}
+
+struct user
+{
+  mystring name;
+  mystring code;
+  user* next;
+  user(const mystring& n, const mystring& c);
+};
+
+user::user(const mystring& n, const mystring& c)
+  : name(n), code(c), next(0)
+{
+}
+
+void show_user(const user* user)
+{
+  vpwentry vpw;
+  vpw.from_record(user->name, user->code);
+  
+  mystring link;
+  mystring elink;
+
+  if(!!userlink) {
+    link = "<a href=\"" + do_subst(userlink, vpw.name) + "\">";
+    elink = "</a>";
+  }
+  
+  fout << "<tr>"
+       << cell_pre << link << vpw.name << elink << cell_post
+       << cell_pre << vpw.mailbox << cell_post;
+  for(mystring_iter iter = vpw.forwards; iter; ++iter)
+    fout << cell_pre << *iter << cell_post;
+  fout << "</tr>\n";
+}
+
+mystring load_users(int fd, unsigned& count, user**& array)
+{
+  user* tail = 0;
+  user* head = 0;
+  for(count = 0; ; count++) {
+    response r(response::read(fd));
+    if(!r)
+      return r.message();
+    if(!r.msg)
+      break;
+    mystring name(r.msg.c_str());
+    mystring code(r.msg.c_str() + name.length()+1,
+		  r.msg.length() - name.length()-1);
+    user* node = new user(name, code);
+    if(!head)
+      head = node;
+    else
+      tail->next = node;
+    tail = node;
+  }
+  if(count) {
+    array = new user*[count];
+    unsigned i = 0;
+    for(user* node = head; node; node = node->next)
+      array[i++] = node;
+  }
+  return "";
+}
+
+static int user_cmp(const void* ptra, const void* ptrb)
+{
+  const user* a = *(const user**)ptra;
+  const user* b = *(const user**)ptrb;
+  int res = a->name != b->name;
+  return res;
+}
+
+void show_domain(int fd)
+{
+  unsigned count = 0;
+  user** users;
+  mystring msg = load_users(fd, count, users);
+  if(count == 0) {
+    fout << p_pre << "This domain contains no users.</p>\n";
+    return;
+  }
+
+  if(!!msg) {
+    fout << p_pre << "<samp>" << msg << "</samp></p>\n";
+    return;
+  }
+
+  qsort(users, count, sizeof users[0], user_cmp);
+  
+  fout << p_pre << "This domain contains " << count << " users:</p>\n";
+  fout << "<table border=1 align=\"" << table_align << "\">\n"
+    "<tr><td><u>Username</u></td>"
+    "<td><u>Mailbox</u></td>"
+    "<td><u>Forwards</u></td></tr>\n";
+  for(unsigned i = 0; i < count; i++)
+    show_user(users[i]);
+  fout << "</table>\n";
+}
+
+void setup_format(const CGIArgs& args)
+{
+  p_pre = "<p align=\"" + args.get("p-align", "left") + "\">";
+
+  cell_pre = args["cell-pre"];
+  cell_post = args["cell-post"];
+  
+  cell_pre = "<td align=\"" + args.get("cell-align", "left") + "\">"
+    + cell_pre;
+  cell_post = cell_post + "</td>";
+
+  userlink = args["userlink"];
+
+  table_align = args.get("table-align", "left");
+}
+
+CGI_MAIN 
+{
+  mystring body_flags = args["body-flags"];
+  mystring title_pre = args.get("title-pre", "<h1>");
+  mystring title_post = args.get("title-post", "</h1>");
+
+  setup_format(args);
+
+  domain = vdomain;
+  server_call call("listdomain", vdomain, password);
+  response resp = call.call();
+  if(!resp)
+    error(resp.msg);
+  else {
+    content_type("text/html");
+    fout << "<html>"
+      "<head>"
+      "<title>Listing of Virtual Domain '" << vdomain << "'</title>"
+      "</head>\n"
+      "<body " << body_flags << ">\n" <<
+      p_pre << title_pre << "Listing of Virtual Domain "
+      "'" << vdomain << "'" << title_post << "</p>"
+      "<hr>\n";
+    show_domain(call.socket());
+    const mystring referer = getenv("HTTP_REFERER");
+    if(!!referer)
+      fout << p_pre << "<a href=\"" << referer << "\">Back</a></p>\n";
+    fout << "</body>\n"
+      "</html>\n";
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/listvdomain.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,14 @@
+<html>
+<head>
+<title>Sample VMailMgr "listvdomain" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "listvdomain" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/listvdomain">
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vaddalias.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,55 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "cgi/cgi-base.h"
+#include "misc/server.h"
+
+CGI_MAIN 
+{
+  CGI_INPUT(username);
+  CGI_OPTINPUT(newpass1);
+  CGI_OPTINPUT(newpass2);
+  CGI_INPUT(destination);
+  
+  username = username.lower();
+
+  if(newpass1 != newpass2) 
+    error("The passwords you entered do not match");
+  else {
+    mystring errmsg;
+    unsigned dests = destination.count(',') + 1;
+
+    server_call call("adduser2", dests + 5);
+    call.operand(0, vdomain);
+    call.operand(1, username);
+    call.operand(2, password);
+    call.operand(3, newpass1);
+    call.operand(4, "");
+    
+    unsigned i = 5;
+    for(mystring_iter iter(destination, ','); iter; ++iter, ++i)
+      call.operand(i, *iter);
+
+    response resp = call.call();
+    if(!resp)
+      errmsg = resp.msg;
+    if(!errmsg)
+      success("The alias was succesfully added.");
+    else
+      error(errmsg);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vaddalias.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,17 @@
+<html>
+<head>
+<title>Sample VMailMgr "vaddalias" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "vaddalias" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/vaddalias">
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p>New virtual user name: <input type=text name=username></p>
+<p>New destination: <input type=text name=destination><br>
+Note: seperate multiple addresses with commas.</p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vadduser.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,55 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "cgi/cgi-base.h"
+#include "misc/server.h"
+
+CGI_MAIN 
+{
+  CGI_INPUT(username);
+  CGI_INPUT(newpass1);
+  CGI_INPUT(newpass2);
+  CGI_OPTINPUT(userdir);
+  CGI_OPTINPUT(destination);
+  
+  username = username.lower();
+
+  unsigned dests = !destination ? 0 : destination.count(',') + 1;
+  
+  if(!userdir)
+    userdir = username;
+  if(newpass1 != newpass2)
+    error("The passwords you entered do not match");
+  else {
+    server_call call("adduser2", dests + 5);
+    call.operand(0, vdomain);
+    call.operand(1, username);
+    call.operand(2, password);
+    call.operand(3, newpass1);
+    call.operand(4, userdir);
+
+    unsigned i = 0;
+    for(mystring_iter iter(destination, ','); i < dests && iter; ++iter, ++i)
+      call.operand(i+5, *iter);
+
+    response resp = call.call();
+    if(!resp)
+      error(resp.msg);
+    else
+      success("The user was succesfully added.");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vadduser.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,20 @@
+<html>
+<head>
+<title>Sample VMailMgr "vadduser" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "vadduser" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/vadduser">
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p>New virtual user name: <input type=text name=username></p>
+<p>New pass phrase: <input type=password name=newpass1></p>
+<p>Type it again: <input type=password name=newpass2></p>
+<p>Virtual user's directory: <input type=text name=userdir><br>
+Note: leave this blank unless you need to set the directory to something
+other than the virtual user's name.</p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vchalias.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,17 @@
+<html>
+<head>
+<title>Sample VMailMgr "vchalias" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "vchalias" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/vchattr">
+<input type=hidden name=attribute value=2>
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p>Virtual user name: <input type=text name=username></p>
+<p>New destination: <input type=text name=newvalue></p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vchattr.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,36 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "cgi/cgi-base.h"
+#include "misc/server.h"
+#include "vdomain/vdomain.h"
+
+CGI_MAIN 
+{
+  CGI_INPUT(username);
+  CGI_INPUT(attribute);
+  CGI_INPUT(newvalue);
+  
+  username = username.lower();
+
+  response resp = server_call("chattr", vdomain, username, password,
+			      attribute, newvalue).call();
+  if(!resp)
+    error(resp.msg);
+  else
+    success("The attribute was succesfully changed.");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vchattr.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,23 @@
+<html>
+<head>
+<title>Sample VMailMgr "vchattr" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "vchattr" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/vchattr">
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p>Virtual user name: <input type=text name=username></p>
+<p>Attribute: <select name=attribute>
+<option value=3>Hard quota
+<option value=4>Soft quota
+<option value=5>Message size limit
+<option value=6>Message count limit
+<option value=7>Account expiry time
+</select></p>
+<p>New value: <input type=text name=newvalue></p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vchforwards.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,68 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "cgi/cgi-base.h"
+#include "misc/server.h"
+#include "vdomain/vdomain.h"
+#include "misc/itoa.h"
+
+CGI_MAIN 
+{
+  CGI_INPUT(username);
+  CGI_INPUT(destination);
+  CGI_OPTINPUT(enable);
+  
+  bool do_disable = (!!enable) && enable == "0";
+  bool do_enable = (!!enable) && enable != "0";
+  
+  username = username.lower();
+
+  // Enable the account *BEFORE* changing the destination
+  if(do_enable) {
+    response resp = server_call("chattr", vdomain, username, password,
+				itoa(vdomain::ATTR_MAILBOX_ENABLED),
+				enable).call();
+    if(!resp)
+      error(resp.msg);
+  }
+  
+  unsigned dests = destination.count(',') + 1;
+
+  server_call call("chattr", dests + 4);
+  call.operand(0, vdomain);
+  call.operand(1, username);
+  call.operand(2, password);
+  call.operand(3, itoa(vdomain::ATTR_DEST));
+
+  unsigned i = 4;
+  for(mystring_iter iter(destination, ','); iter; ++iter, ++i)
+    call.operand(i, *iter);
+
+  response resp = call.call();
+  if(!resp)
+    error(resp.msg);
+
+  // Disable the account *AFTER* changing the destination.
+  if(do_disable) {
+    response resp = server_call("chattr", vdomain, username, password,
+				itoa(vdomain::ATTR_MAILBOX_ENABLED),
+				enable).call();
+    if(!resp)
+      error(resp.msg);
+  }
+  success("The alias was succesfully changed.");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vchforwards.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>Sample VMailMgr "vchforwards" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "vchforwards" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/vchforwards">
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p>Virtual user name: <input type=text name=username></p>
+<p>New destination: <input type=text name=destination><br>
+Note: seperate multiple addresses with commas.</p>
+<p>Enable/Disable Mailbox Delivery: <select name=enable>
+<option value="">No change
+<option value="0">Disable
+<option value="1">Enable
+</select></p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vdeluser.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,32 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "cgi/cgi-base.h"
+#include "misc/server.h"
+
+CGI_MAIN 
+{
+  CGI_INPUT(username);
+  
+  username = username.lower();
+
+  response resp = server_call("deluser", vdomain, username, password).call();
+  if(!resp)
+    error(resp.msg);
+  else
+    success("The user was succesfully deleted.");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vdeluser.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,15 @@
+<html>
+<head>
+<title>Sample VMailMgr "vdeluser" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "vdeluser" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/vdeluser">
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p>Virtual user name: <input type=text name=username></p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vpasswd.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,41 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "cgi/cgi-base.h"
+#include "misc/server.h"
+#include "vdomain/vdomain.h"
+#include "misc/itoa.h"
+
+CGI_MAIN 
+{
+  CGI_INPUT(username);
+  CGI_INPUT(newpass1);
+  CGI_INPUT(newpass2);
+  
+  username = username.lower();
+
+  if(newpass1 != newpass2)
+    error("The passwords you entered do not match");
+  else {
+    response resp = server_call("chattr", vdomain, username, password,
+				itoa(vdomain::ATTR_PASS), newpass1).call();
+    if(!resp)
+      error(resp.msg);
+    else
+      success("The password was succesfully changed.");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi/vpasswd.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,17 @@
+<html>
+<head>
+<title>Sample VMailMgr "vpasswd" Page</title>
+</head>
+<body>
+<center><p><h1>Sample VMailMgr "vpasswd" Page</h1></p></center>
+<hr>
+<form method=post action="/cgi-bin/vpasswd">
+<p>Domain name: <input type=text name=vdomain></p>
+<p>Pass phrase: <input type=password name=password></p>
+<p>Virtual user name: <input type=text name=username></p>
+<p>New pass phrase: <input type=password name=newpass1></p>
+<p>Type it again: <input type=password name=newpass2></p>
+<p><input type=submit></p>
+</form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,84 @@
+bin_PROGRAMS = @CDBPROGS@ \
+	listvdomain vadduser vaddusers vchattr vchforwards vcheckquota \
+	vdeliver vdeluser vpasswd vpasswd2db vpasswds vpopbull vsetup
+bin_SCRIPTS = @CDBSCRIPTS@ vaddalias vconf2dir
+noinst_HEADERS = vcommand.h
+
+noinst_PODS = vpasswd2cdb.pod vrehash.pod \
+	listvdomain.pod vadduser.pod vadduser.pod vchattr.pod \
+	vchforwards.pod vcheckquota.pod vdeliver.pod vdeluser.pod \
+	vpasswd.pod vpasswd2db.pod vpasswds.pod vpopbull.pod vsetup.pod
+noinst_HTMLS = $(noinst_PODS:.pod=.html)
+man_MANS = $(noinst_PODS:.pod=.1)
+
+CLEANFILES = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS) \
+	pod2html-dircache pod2html-itemcache
+EXTRA_DIST = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS) $(bin_SCRIPTS) \
+	vpasswd2cdb.cc vrehash.cc
+
+EXTRA_PROGRAMS = vpasswd2cdb vrehash
+EXTRA_SCRIPTS = allvpasswd2cdb
+
+all: docs
+
+docs: $(noinst_HTMLS) $(man_MANS)
+
+dist-hook:
+	touch $(distdir)/*.html $(distdir)/*.[123456789]
+
+%.pod: %.cc ../configure.in ../lib/cli/cli2pod.pl
+	perl ../lib/cli/cli2pod.pl $< >$@
+%.1: %.pod ../configure.in; $(POD2MAN) --section=1 $< >$@
+%.html: %.pod; $(POD2HTML) $< >$@
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = -I../lib -DBINDIR=\"@bindir@\"
+
+listvdomain_SOURCES = listvdomain.cc vcommand.cc
+listvdomain_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vadduser_SOURCES = vadduser.cc vcommand.cc
+vadduser_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vaddusers_SOURCES = vaddusers.cc vcommand.cc
+vaddusers_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vchattr_SOURCES = vchattr.cc vcommand.cc
+vchattr_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vcheckquota_SOURCES = vcheckquota.cc
+vcheckquota_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vchforwards_SOURCES = vchforwards.cc vcommand.cc
+vchforwards_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vdeliver_SOURCES = vdeliver.cc vcommand.cc
+vdeliver_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vdeluser_SOURCES = vdeluser.cc vcommand.cc
+vdeluser_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpasswd_SOURCES = vpasswd.cc vcommand.cc
+vpasswd_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpasswds_SOURCES = vpasswds.cc vcommand.cc
+vpasswds_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpasswd2db_SOURCES = vpasswd2db.cc vcommand.cc
+vpasswd2db_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpopbull_SOURCES = vpopbull.cc vcommand.cc
+vpopbull_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vsetup_SOURCES = vsetup.cc vcommand.cc
+vsetup_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+if VPWTABLE_CDB
+
+vpasswd2cdb_SOURCES = vpasswd2cdb.cc vcommand.cc
+vpasswd2cdb_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vrehash_SOURCES = vrehash.cc vcommand.cc
+vrehash_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,676 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+bin_PROGRAMS = @CDBPROGS@ 	listvdomain vadduser vaddusers vchattr vchforwards vcheckquota 	vdeliver vdeluser vpasswd vpasswd2db vpasswds vpopbull vsetup
+
+bin_SCRIPTS = @CDBSCRIPTS@ vaddalias vconf2dir
+noinst_HEADERS = vcommand.h
+
+noinst_PODS = vpasswd2cdb.pod vrehash.pod 	listvdomain.pod vadduser.pod vadduser.pod vchattr.pod 	vchforwards.pod vcheckquota.pod vdeliver.pod vdeluser.pod 	vpasswd.pod vpasswd2db.pod vpasswds.pod vpopbull.pod vsetup.pod
+
+noinst_HTMLS = $(noinst_PODS:.pod=.html)
+man_MANS = $(noinst_PODS:.pod=.1)
+
+CLEANFILES = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS) 	pod2html-dircache pod2html-itemcache
+
+EXTRA_DIST = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS) $(bin_SCRIPTS) 	vpasswd2cdb.cc vrehash.cc
+
+
+EXTRA_PROGRAMS = vpasswd2cdb vrehash
+EXTRA_SCRIPTS = allvpasswd2cdb
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = -I../lib -DBINDIR=\"@bindir@\"
+
+listvdomain_SOURCES = listvdomain.cc vcommand.cc
+listvdomain_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vadduser_SOURCES = vadduser.cc vcommand.cc
+vadduser_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vaddusers_SOURCES = vaddusers.cc vcommand.cc
+vaddusers_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vchattr_SOURCES = vchattr.cc vcommand.cc
+vchattr_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vcheckquota_SOURCES = vcheckquota.cc
+vcheckquota_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vchforwards_SOURCES = vchforwards.cc vcommand.cc
+vchforwards_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vdeliver_SOURCES = vdeliver.cc vcommand.cc
+vdeliver_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vdeluser_SOURCES = vdeluser.cc vcommand.cc
+vdeluser_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpasswd_SOURCES = vpasswd.cc vcommand.cc
+vpasswd_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpasswds_SOURCES = vpasswds.cc vcommand.cc
+vpasswds_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpasswd2db_SOURCES = vpasswd2db.cc vcommand.cc
+vpasswd2db_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vpopbull_SOURCES = vpopbull.cc vcommand.cc
+vpopbull_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+vsetup_SOURCES = vsetup.cc vcommand.cc
+vsetup_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+@VPWTABLE_CDB_TRUE@vpasswd2cdb_SOURCES = vpasswd2cdb.cc vcommand.cc
+@VPWTABLE_CDB_TRUE@vpasswd2cdb_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+
+@VPWTABLE_CDB_TRUE@vrehash_SOURCES = vrehash.cc vcommand.cc
+@VPWTABLE_CDB_TRUE@vrehash_LDADD = ../lib/libcli.a ../lib/libvmailmgr.a
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+@VPWTABLE_CDB_TRUE@vpasswd2cdb_OBJECTS =  vpasswd2cdb.o vcommand.o
+@VPWTABLE_CDB_TRUE@vpasswd2cdb_DEPENDENCIES =  ../lib/libcli.a \
+@VPWTABLE_CDB_TRUE@../lib/libvmailmgr.a
+vpasswd2cdb_LDFLAGS = 
+@VPWTABLE_CDB_TRUE@vrehash_OBJECTS =  vrehash.o vcommand.o
+@VPWTABLE_CDB_TRUE@vrehash_DEPENDENCIES =  ../lib/libcli.a \
+@VPWTABLE_CDB_TRUE@../lib/libvmailmgr.a
+vrehash_LDFLAGS = 
+listvdomain_OBJECTS =  listvdomain.o vcommand.o
+listvdomain_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+listvdomain_LDFLAGS = 
+vadduser_OBJECTS =  vadduser.o vcommand.o
+vadduser_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vadduser_LDFLAGS = 
+vaddusers_OBJECTS =  vaddusers.o vcommand.o
+vaddusers_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vaddusers_LDFLAGS = 
+vchattr_OBJECTS =  vchattr.o vcommand.o
+vchattr_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vchattr_LDFLAGS = 
+vchforwards_OBJECTS =  vchforwards.o vcommand.o
+vchforwards_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vchforwards_LDFLAGS = 
+vcheckquota_OBJECTS =  vcheckquota.o
+vcheckquota_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vcheckquota_LDFLAGS = 
+vdeliver_OBJECTS =  vdeliver.o vcommand.o
+vdeliver_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vdeliver_LDFLAGS = 
+vdeluser_OBJECTS =  vdeluser.o vcommand.o
+vdeluser_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vdeluser_LDFLAGS = 
+vpasswd_OBJECTS =  vpasswd.o vcommand.o
+vpasswd_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vpasswd_LDFLAGS = 
+vpasswd2db_OBJECTS =  vpasswd2db.o vcommand.o
+vpasswd2db_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vpasswd2db_LDFLAGS = 
+vpasswds_OBJECTS =  vpasswds.o vcommand.o
+vpasswds_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vpasswds_LDFLAGS = 
+vpopbull_OBJECTS =  vpopbull.o vcommand.o
+vpopbull_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vpopbull_LDFLAGS = 
+vsetup_OBJECTS =  vsetup.o vcommand.o
+vsetup_DEPENDENCIES =  ../lib/libcli.a ../lib/libvmailmgr.a
+vsetup_LDFLAGS = 
+SCRIPTS =  $(bin_SCRIPTS)
+
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+HEADERS =  $(noinst_HEADERS)
+
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(vpasswd2cdb_SOURCES) $(vrehash_SOURCES) $(listvdomain_SOURCES) $(vadduser_SOURCES) $(vaddusers_SOURCES) $(vchattr_SOURCES) $(vchforwards_SOURCES) $(vcheckquota_SOURCES) $(vdeliver_SOURCES) $(vdeluser_SOURCES) $(vpasswd_SOURCES) $(vpasswd2db_SOURCES) $(vpasswds_SOURCES) $(vpopbull_SOURCES) $(vsetup_SOURCES)
+OBJECTS = $(vpasswd2cdb_OBJECTS) $(vrehash_OBJECTS) $(listvdomain_OBJECTS) $(vadduser_OBJECTS) $(vaddusers_OBJECTS) $(vchattr_OBJECTS) $(vchforwards_OBJECTS) $(vcheckquota_OBJECTS) $(vdeliver_OBJECTS) $(vdeluser_OBJECTS) $(vpasswd_OBJECTS) $(vpasswd2db_OBJECTS) $(vpasswds_OBJECTS) $(vpopbull_OBJECTS) $(vsetup_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps commands/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "  $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	     $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+vpasswd2cdb: $(vpasswd2cdb_OBJECTS) $(vpasswd2cdb_DEPENDENCIES)
+	@rm -f vpasswd2cdb
+	$(CXXLINK) $(vpasswd2cdb_LDFLAGS) $(vpasswd2cdb_OBJECTS) $(vpasswd2cdb_LDADD) $(LIBS)
+
+vrehash: $(vrehash_OBJECTS) $(vrehash_DEPENDENCIES)
+	@rm -f vrehash
+	$(CXXLINK) $(vrehash_LDFLAGS) $(vrehash_OBJECTS) $(vrehash_LDADD) $(LIBS)
+
+listvdomain: $(listvdomain_OBJECTS) $(listvdomain_DEPENDENCIES)
+	@rm -f listvdomain
+	$(CXXLINK) $(listvdomain_LDFLAGS) $(listvdomain_OBJECTS) $(listvdomain_LDADD) $(LIBS)
+
+vadduser: $(vadduser_OBJECTS) $(vadduser_DEPENDENCIES)
+	@rm -f vadduser
+	$(CXXLINK) $(vadduser_LDFLAGS) $(vadduser_OBJECTS) $(vadduser_LDADD) $(LIBS)
+
+vaddusers: $(vaddusers_OBJECTS) $(vaddusers_DEPENDENCIES)
+	@rm -f vaddusers
+	$(CXXLINK) $(vaddusers_LDFLAGS) $(vaddusers_OBJECTS) $(vaddusers_LDADD) $(LIBS)
+
+vchattr: $(vchattr_OBJECTS) $(vchattr_DEPENDENCIES)
+	@rm -f vchattr
+	$(CXXLINK) $(vchattr_LDFLAGS) $(vchattr_OBJECTS) $(vchattr_LDADD) $(LIBS)
+
+vchforwards: $(vchforwards_OBJECTS) $(vchforwards_DEPENDENCIES)
+	@rm -f vchforwards
+	$(CXXLINK) $(vchforwards_LDFLAGS) $(vchforwards_OBJECTS) $(vchforwards_LDADD) $(LIBS)
+
+vcheckquota: $(vcheckquota_OBJECTS) $(vcheckquota_DEPENDENCIES)
+	@rm -f vcheckquota
+	$(CXXLINK) $(vcheckquota_LDFLAGS) $(vcheckquota_OBJECTS) $(vcheckquota_LDADD) $(LIBS)
+
+vdeliver: $(vdeliver_OBJECTS) $(vdeliver_DEPENDENCIES)
+	@rm -f vdeliver
+	$(CXXLINK) $(vdeliver_LDFLAGS) $(vdeliver_OBJECTS) $(vdeliver_LDADD) $(LIBS)
+
+vdeluser: $(vdeluser_OBJECTS) $(vdeluser_DEPENDENCIES)
+	@rm -f vdeluser
+	$(CXXLINK) $(vdeluser_LDFLAGS) $(vdeluser_OBJECTS) $(vdeluser_LDADD) $(LIBS)
+
+vpasswd: $(vpasswd_OBJECTS) $(vpasswd_DEPENDENCIES)
+	@rm -f vpasswd
+	$(CXXLINK) $(vpasswd_LDFLAGS) $(vpasswd_OBJECTS) $(vpasswd_LDADD) $(LIBS)
+
+vpasswd2db: $(vpasswd2db_OBJECTS) $(vpasswd2db_DEPENDENCIES)
+	@rm -f vpasswd2db
+	$(CXXLINK) $(vpasswd2db_LDFLAGS) $(vpasswd2db_OBJECTS) $(vpasswd2db_LDADD) $(LIBS)
+
+vpasswds: $(vpasswds_OBJECTS) $(vpasswds_DEPENDENCIES)
+	@rm -f vpasswds
+	$(CXXLINK) $(vpasswds_LDFLAGS) $(vpasswds_OBJECTS) $(vpasswds_LDADD) $(LIBS)
+
+vpopbull: $(vpopbull_OBJECTS) $(vpopbull_DEPENDENCIES)
+	@rm -f vpopbull
+	$(CXXLINK) $(vpopbull_LDFLAGS) $(vpopbull_OBJECTS) $(vpopbull_LDADD) $(LIBS)
+
+vsetup: $(vsetup_OBJECTS) $(vsetup_DEPENDENCIES)
+	@rm -f vsetup
+	$(CXXLINK) $(vsetup_LDFLAGS) $(vsetup_OBJECTS) $(vsetup_LDADD) $(LIBS)
+
+install-binSCRIPTS: $(bin_SCRIPTS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_SCRIPTS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; fi; \
+	done
+
+uninstall-binSCRIPTS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_SCRIPTS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+	done
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+install-man1:
+	$(mkinstalldirs) $(DESTDIR)$(man1dir)
+	@list='$(man1_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+	  $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+	done
+
+uninstall-man1:
+	@list='$(man1_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+	  rm -f $(DESTDIR)$(man1dir)/$$inst; \
+	done
+install-man: $(MANS)
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+	@$(NORMAL_UNINSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = commands
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+listvdomain.o: listvdomain.cc ../config.h ../lib/config/configrc.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/strlist.h ../lib/vpwentry/vpwentry.h \
+	../lib/cli/cli.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h vcommand.h ../lib/vdomain/vdomain.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/misc/response.h
+vadduser.o: vadduser.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/misc/passwdfn.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/misc/pwcrypt.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h ../lib/cli/cli.h
+vaddusers.o: vaddusers.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/pwcrypt.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/cli/cli.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h
+vchattr.o: vchattr.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/passwdfn.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/cli/cli.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h
+vcheckquota.o: vcheckquota.cc ../config.h ../lib/config/configrc.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/strlist.h ../lib/cli/cli.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h ../lib/ac/dirent.h ../lib/misc/itoa.h \
+	../lib/misc/stat_fns.h ../lib/misc/md5.h ../lib/misc/strtou.h \
+	../lib/misc/utoa.h
+vchforwards.o: vchforwards.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h ../lib/cli/cli.h \
+	vcommand.h ../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h
+vcommand.o: vcommand.cc ../config.h vcommand.h ../lib/vdomain/vdomain.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/response.h \
+	../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+vdeliver.o: vdeliver.cc ../config.h ../lib/ac/time.h ../lib/ac/wait.h \
+	../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h ../lib/cli/cli.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h ../lib/misc/itoa.h \
+	../lib/misc/stat_fns.h ../lib/misc/exec.h
+vdeluser.o: vdeluser.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/config/configrc.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/strlist.h ../lib/cli/cli.h \
+	vcommand.h ../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h
+vpasswd.o: vpasswd.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/passwdfn.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/cli/cli.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h
+vpasswd2cdb.o: vpasswd2cdb.cc ../config.h ../lib/cdb++/cdb++.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/cdb++/datum.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h ../lib/cli/cli.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vpwentry/vpwentry.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h
+vpasswd2db.o: vpasswd2db.cc ../config.h ../lib/cli/cli.h \
+	../lib/config/configrc.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/strlist.h \
+	../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h ../lib/vpwentry/vpwentry.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h
+vpasswds.o: vpasswds.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/response.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/cli/cli.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h
+vpopbull.o: vpopbull.cc ../config.h ../lib/ac/dirent.h ../lib/ac/time.h \
+	../lib/misc/itoa.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/cli/cli.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h vcommand.h \
+	../lib/vdomain/vdomain.h ../lib/misc/pwentry.h \
+	../lib/vpwtable/vpwtable.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/response.h
+vrehash.o: vrehash.cc ../config.h ../lib/misc/autodelete.h \
+	../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/maildir.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h vcommand.h ../lib/vdomain/vdomain.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/misc/response.h ../lib/misc/stat_fns.h ../lib/cli/cli.h \
+	../lib/cdb++/cdb++.h ../lib/cdb++/datum.h
+vsetup.o: vsetup.cc ../config.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/config/configrc.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/strlist.h \
+	../lib/misc/stat_fns.h ../lib/cli/cli.h ../lib/misc/exec.h \
+	../lib/vpwentry/vpwentry.h vcommand.h ../lib/vdomain/vdomain.h \
+	../lib/misc/pwentry.h ../lib/vpwtable/vpwtable.h \
+	../lib/misc/response.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS install-binSCRIPTS
+install-exec: install-exec-am
+
+install-data-am: install-man
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(MANS) $(HEADERS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(bindir) $(DESTDIR)$(bindir) \
+		$(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-binPROGRAMS clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-binPROGRAMS distclean-compile distclean-tags \
+		distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-binPROGRAMS \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile uninstall-binSCRIPTS install-binSCRIPTS \
+install-man1 uninstall-man1 install-man uninstall-man tags \
+mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \
+distdir info-am info dvi-am dvi check check-am installcheck-am \
+installcheck install-exec-am install-exec install-data-am install-data \
+install-am install uninstall-am uninstall all-redirect all-am all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+all: docs
+
+docs: $(noinst_HTMLS) $(man_MANS)
+
+dist-hook:
+	touch $(distdir)/*.html $(distdir)/*.[123456789]
+
+%.pod: %.cc ../configure.in ../lib/cli/cli2pod.pl
+	perl ../lib/cli/cli2pod.pl $< >$@
+%.1: %.pod ../configure.in; $(POD2MAN) --section=1 $< >$@
+%.html: %.pod; $(POD2HTML) $< >$@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/allvpasswd2cdb	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,19 @@
+#!/bin/sh
+while IFS=: read name pass uid gid gecos home shell; do
+  echo -n "$name($uid): "
+  if ! cd "$home" 2>/dev/null; then
+    echo Skipping, has invalid home directory.
+    continue
+  fi
+  if [ -f passwd -a -d users ] && \
+     fgrep vdeliver .qmail-default >/dev/null 2>&1; then
+    if [ -f passwd.cdb ]; then
+      echo Skipping, has already been converted.
+    else
+      su - $name sh -c 'exec vpasswd2cdb'
+      echo Converted.
+    fi
+  else
+    echo Skipping, is missing a passwd file.
+  fi
+done </etc/passwd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/listvdomain.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,235 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH LISTVDOMAIN 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+listvdomain \- Lists the members of a virtual domain
+.SH "SYNOPSIS"
+\fBlistvdomain\fR
+[\fB\-a\fR]
+[\fB--aliases\fR]
+[\fB--quiet\fR]
+[\fB\-u\fR]
+[\fB--users\fR]
+\fI[user [user ...]]\fR
+.SH "DESCRIPTION"
+This program lists all the users in a domain.
+The listing consists of one user per line,
+and each line has three columns:
+the virtual user name, the mailbox directory (or \f(CW-\fR if none is set),
+and an optional list of forwarding addresses, all seperated by a space.
+.SH "OPTIONS"
+.Ip "\fB\-a\fR, \fB--aliases\fR" 8
+Show only accounts without a mailbox.
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.Ip "\fB\-u\fR, \fB--users\fR" 8
+Show only accounts with a mailbox.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "LISTVDOMAIN 1"
+.IX Name "listvdomain - Lists the members of a virtual domain"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB\-a\fR, \fB--aliases\fR"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Item "\fB\-u\fR, \fB--users\fR"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/listvdomain.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,114 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "config/configrc.h"
+#include "vpwentry/vpwentry.h"
+#include "cli/cli.h"
+#include "fdbuf/fdbuf.h"
+#include "vcommand.h"
+
+const char* cli_program = "listvdomain";
+const char* cli_help_prefix = "Lists the members of a virtual domain\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "[user [user ...]]";
+const int cli_args_min = 0;
+const int cli_args_max = -1;
+static int o_noaliases = false;
+static int o_nousers = false;
+static int o_quiet = false;
+
+// This program lists all the users in a domain.
+// The listing consists of one user per line,
+// and each line has three columns:
+// the virtual user name, the mailbox directory (or C<-> if none is set),
+// and an optional list of forwarding addresses, all seperated by a space.
+
+cli_option cli_options[] = {
+  { 'a', "aliases", cli_option::flag, true, &o_nousers,
+    "Show only accounts without a mailbox", 0 },
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  { 'u', "users", cli_option::flag, true, &o_noaliases,
+    "Show only accounts with a mailbox", 0 },
+  {0}  
+};
+
+void show_user(const vpwentry& vpw)
+{
+  if(o_noaliases && !vpw.mailbox)
+    return;
+  if(o_nousers && !!vpw.mailbox)
+    return;
+  fout << vpw.name;
+  if(!vpw.mailbox)
+    fout << " -";
+  else {
+    fout << ' ' << vpw.mailbox;
+    if(!vpw.is_mailbox_enabled)
+      fout << "(disabled)";
+  }
+  for(mystring_iter iter(vpw.forwards, '\0'); iter; ++iter)
+    fout << ' ' << *iter;
+  fout << '\n';
+}
+
+int cli_main(int argc, char* argv[])
+{
+  if(!go_home())
+    return 1;
+
+  int errors = 0;
+  
+  if(o_noaliases && o_nousers) {
+    if(!o_quiet)
+      ferr << "listvdomain: specify only one of -a and -u" << endl;
+    return 1;
+  }
+  
+  vpwtable* table = domain.table();
+
+  fout << "User Mailbox Aliases\n";
+  
+  if(argc) {
+    vpwentry* vpw;
+    for(int i = 0; i < argc; i++) {
+      vpw = table->getbyname(argv[i]);
+      if(!vpw) {
+	if(!o_quiet)
+	  ferr << "listvdomain: unknown user '" << argv[i] << "'" << endl;
+	errors = 1;
+      }
+      else {
+	show_user(*vpw);
+	delete vpw;
+      }
+    }
+  }
+  else {
+    vpwtable_reader* r = table->start_read();
+    if(!*r) {
+      if(!o_quiet)
+	ferr << "listvdomain: Can't open password table" << endl;
+      return 1;
+    }
+    vpwentry vpw;
+    while(r->get(vpw))
+      show_user(vpw);
+    delete r;
+  }
+  return errors;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/listvdomain.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,72 @@
+<HTML>
+<HEAD>
+<TITLE>listvdomain - Lists the members of a virtual domain</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+listvdomain - Lists the members of a virtual domain
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>listvdomain</STRONG>
+[<STRONG>-a</STRONG>] [<STRONG>--aliases</STRONG>] [<STRONG>--quiet</STRONG>] [<STRONG>-u</STRONG>] [<STRONG>--users</STRONG>]
+<EM>[user [user ...]]</EM>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program lists all the users in a domain. The listing consists of one
+user per line, and each line has three columns: the virtual user name, the
+mailbox directory (or <CODE>-</CODE> if none is set), and an optional list of forwarding addresses, all
+seperated by a space.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__a_">-a, --aliases</A></STRONG><DD>
+<P>
+Show only accounts without a mailbox.
+
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+<DT><STRONG><A NAME="item__u_">-u, --users</A></STRONG><DD>
+<P>
+Show only accounts with a mailbox.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/listvdomain.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,45 @@
+=head1 NAME
+
+listvdomain - Lists the members of a virtual domain
+
+=head1 SYNOPSIS
+
+B<listvdomain>
+[B<-a>]
+[B<--aliases>]
+[B<--quiet>]
+[B<-u>]
+[B<--users>]
+I<[user [user ...]]>
+
+=head1 DESCRIPTION
+
+This program lists all the users in a domain.
+The listing consists of one user per line,
+and each line has three columns:
+the virtual user name, the mailbox directory (or C<-> if none is set),
+and an optional list of forwarding addresses, all seperated by a space.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-a>, B<--aliases>
+
+Show only accounts without a mailbox.
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=item B<-u>, B<--users>
+
+Show only accounts with a mailbox.
+
+=back
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vaddalias	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -e
+if [ $# -lt 2 ]; then
+  echo "usage: vaddalias virtuser dest [dest ...]"
+  exit 1
+fi
+user="$1"
+shift 1
+args="-D -P"
+for dest in "$@"; do
+  args="$args -f '$dest'"
+done
+eval exec vadduser $args "$user"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vadduser.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,307 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VADDUSER 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vadduser \- Add a user to a virtual domain
+.SH "SYNOPSIS"
+\fBvadduser\fR
+[\fB\-c INT\fR]
+[\fB--msgcount=INT\fR]
+[\fB\-D\fR]
+[\fB--no-mailbox\fR]
+[\fB\-d STR\fR]
+[\fB--directory=STR\fR]
+[\fB\-e INT\fR]
+[\fB--expiry=INT\fR]
+[\fB\-f STR\fR]
+[\fB--forward=STR\fR]
+[\fB\-P\fR]
+[\fB--no-password\fR]
+[\fB\-p STR\fR]
+[\fB--personal=STR\fR]
+[\fB\-Q INT\fR]
+[\fB--hardquota=INT\fR]
+[\fB\-q INT\fR]
+[\fB--softquota=INT\fR]
+[\fB--quiet\fR]
+[\fB\-z INT\fR]
+[\fB--msgsize=INT\fR]
+\fIUSERNAME [ALIAS1 ...]\en"
+\*(L"or vaddalias [\-f ADDRESS] USERNAME [ALIAS1 ...]\fR
+.SH "DESCRIPTION"
+This program is used to set up a user within a virtual host.
+If this program is reading from a tty,
+it will then ask for a password (twice, to make sure you typed it in
+correctly), otherwise it will read the password from the input with no
+prompting.
+It will then
+add the user to the virtual password table in the current
+directory and create a mail directory for the new user.
+It will also add an entry for each of the named aliases.
+.SH "OPTIONS"
+.Ip "\fB\-c \s-1INT\s0\fR, \fB--msgcount=\s-1INT\s0\fR" 8
+Set the user's message count limit.
+.Ip "\fB\-D\fR, \fB--no-mailbox\fR" 8
+Do not create a mailbox for this user. Defaults to true for vaddalias.
+.Ip "\fB\-d \s-1STR\s0\fR, \fB--directory=\s-1STR\s0\fR" 8
+Set the path to the user's mailbox. Note that this directory is unconditionally prefixed with \*(L"./\*(R".
+.Ip "\fB\-e \s-1INT\s0\fR, \fB--expiry=\s-1INT\s0\fR" 8
+Set the account's expiry time (in seconds).
+.Ip "\fB\-f \s-1STR\s0\fR, \fB--forward=\s-1STR\s0\fR" 8
+Add a forwarding address to this user (this may be used multiple times).
+.Ip "\fB\-P\fR, \fB--no-password\fR" 8
+Do not ask for a password, and instead set the pass phrase field to an unusable value.
+.Ip "\fB\-p \s-1STR\s0\fR, \fB--personal=\s-1STR\s0\fR" 8
+Set the user's personal information.
+.Ip "\fB\-Q \s-1INT\s0\fR, \fB--hardquota=\s-1INT\s0\fR" 8
+Set the user's hard quota (in bytes).
+.Ip "\fB\-q \s-1INT\s0\fR, \fB--softquota=\s-1INT\s0\fR" 8
+Set the user's soft quota (in bytes).
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.Ip "\fB\-z \s-1INT\s0\fR, \fB--msgsize=\s-1INT\s0\fR" 8
+Set the user's message size limit (in bytes).
+.SH "RETURN VALUE"
+0 if all steps were successful, non-zero otherwise.
+If any of the steps fail, a diagnostic message is printed.
+.SH "SEE ALSO"
+\fIvsetup\fR\|(1)
+.SH "NOTES"
+You must have either created the users subdirectory by hand or run the
+\fIvsetup\fR program before using this program.
+.PP
+This program expects the environment variable \f(CWHOME\fR to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VADDUSER 1"
+.IX Name "vadduser - Add a user to a virtual domain"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB\-c \s-1INT\s0\fR, \fB--msgcount=\s-1INT\s0\fR"
+
+.IX Item "\fB\-D\fR, \fB--no-mailbox\fR"
+
+.IX Item "\fB\-d \s-1STR\s0\fR, \fB--directory=\s-1STR\s0\fR"
+
+.IX Item "\fB\-e \s-1INT\s0\fR, \fB--expiry=\s-1INT\s0\fR"
+
+.IX Item "\fB\-f \s-1STR\s0\fR, \fB--forward=\s-1STR\s0\fR"
+
+.IX Item "\fB\-P\fR, \fB--no-password\fR"
+
+.IX Item "\fB\-p \s-1STR\s0\fR, \fB--personal=\s-1STR\s0\fR"
+
+.IX Item "\fB\-Q \s-1INT\s0\fR, \fB--hardquota=\s-1INT\s0\fR"
+
+.IX Item "\fB\-q \s-1INT\s0\fR, \fB--softquota=\s-1INT\s0\fR"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Item "\fB\-z \s-1INT\s0\fR, \fB--msgsize=\s-1INT\s0\fR"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "SEE ALSO"
+
+.IX Header "NOTES"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vadduser.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,242 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <time.h>
+#include "fdbuf/fdbuf.h"
+#include "misc/passwdfn.h"
+#include "mystring/mystring.h"
+#include "config/configrc.h"
+#include "misc/pwcrypt.h"
+#include "vcommand.h"
+#include "cli/cli.h"
+
+const char* cli_program = "vadduser";
+const char* cli_help_prefix = "Add a user to a virtual domain\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "USERNAME [ALIAS1 ...]\n"
+"or vaddalias [-f ADDRESS] USERNAME [ALIAS1 ...]";
+const int cli_args_min = 1;
+const int cli_args_max = -1;
+
+static const char* o_userdir = 0;
+static cli_stringlist* o_forwards = 0;
+static const char* o_personal = 0;
+static int o_softquota = 0;
+static int o_hardquota = 0;
+static int o_msgsize = 0;
+static int o_msgcount = 0;
+static int o_expiry = 0;
+static int o_password = true;
+static int o_domailbox = true;
+static int o_quiet = false;
+
+// This program is used to set up a user within a virtual host.
+// If this program is reading from a tty,
+// it will then ask for a password (twice, to make sure you typed it in
+// correctly), otherwise it will read the password from the input with no
+// prompting.
+// It will then
+// add the user to the virtual password table in the current
+// directory and create a mail directory for the new user.
+// It will also add an entry for each of the named aliases.
+
+cli_option cli_options[] = {
+  { 'c', "msgcount", cli_option::integer, 0, &o_msgcount,
+    "Set the user's message count limit", 0 },
+  { 'D', "no-mailbox", cli_option::flag, false, &o_domailbox,
+    "Do not create a mailbox for this user", "true for vaddalias" },
+  { 'd', "directory", cli_option::string, 0, &o_userdir,
+    "Set the path to the user's mailbox", 0 },
+  // Set the path to the user's mailbox.
+  // Note that this directory is unconditionally prefixed with "./".
+  { 'e', "expiry", cli_option::integer, 0, &o_expiry,
+    "Set the account's expiry time (in seconds)", 0 },
+  { 'f', "forward", cli_option::stringlist, 0, &o_forwards,
+    "Add a forwarding address to this user", 0 },
+  // Add a forwarding address to this user (this may be used multiple times).
+  { 'P', "no-password", cli_option::flag, false, &o_password,
+    "Do not ask for a password", 0 },
+  // Do not ask for a password,
+  // and instead set the pass phrase field to an unusable value.
+  { 'p', "personal", cli_option::string, 0, &o_personal,
+    "Set the user's personal information", 0 },
+  { 'Q', "hardquota", cli_option::integer, 0, &o_hardquota,
+    "Set the user's hard quota (in bytes)", 0 },
+  { 'q', "softquota", cli_option::integer, 0, &o_softquota,
+    "Set the user's soft quota (in bytes)", 0 },
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  { 'z', "msgsize", cli_option::integer, 0, &o_msgsize,
+    "Set the user's message size limit (in bytes)", 0 },
+  {0}
+};
+
+// RETURN VALUE
+//
+// 0 if all steps were successful, non-zero otherwise.
+// If any of the steps fail, a diagnostic message is printed.
+
+// SEE ALSO
+//
+// vsetup(1)
+
+// NOTES
+// You must have either created the users subdirectory by hand or run the
+// F<vsetup> program before using this program.
+// 
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.  It
+// is also required that you change user to the domain owner before using
+// these utilities.
+
+mystring list2str(cli_stringlist* list)
+{
+  if(!list)
+    return 0;
+  mystring result = list->string;
+  list = list->next;
+  while(list) {
+    result = result + mystring::NUL + list->string;
+    list = list->next;
+  }
+  return result;
+}
+
+vpwentry* make_user(const mystring& name, const mystring& passcode)
+{
+  mystring dir;
+  if(o_domailbox) {
+    if(o_userdir)
+      dir = o_userdir;
+    else
+      dir = domain.userdir(name);
+    dir = "./" + dir;
+  }
+
+  for(cli_stringlist* node = o_forwards; node; node = node->next) {
+    response r = domain.validate_forward(node->string);
+    if(!r) {
+      if(!o_quiet)
+	ferr << argv0base << ": invalid forwarding address:\n  "
+	     << r.msg << endl;
+      exit(1);
+    }
+  }
+  
+  vpwentry* vpw = new vpwentry(name.lower(), passcode, dir,
+			       list2str(o_forwards));
+  vpw->set_defaults(true, true);
+  
+  vpw->personal = o_personal;
+  vpw->hardquota = o_hardquota;
+  vpw->softquota = o_softquota;
+  vpw->msgcount = o_msgcount;
+  vpw->msgsize = o_msgsize;
+  vpw->expiry = o_expiry;
+  //vpw->data = list2str(o_extra);
+  
+  return vpw;
+}
+
+void add_user(const mystring& user)
+{
+  if(!domain.exists(user)) {
+    mystring passcode = "*";
+    if(o_password) {
+      mystring passwd = getpasswd(argv0base);
+      if(passwd.length() == 0)
+	exit(1);
+      passcode = pwcrypt(passwd);
+    }
+    vpwentry* vpw = make_user(user, passcode);
+    response resp = domain.set(vpw, true, vpw->mailbox);
+    delete vpw;
+    if(!resp) {
+      if(!o_quiet)
+	ferr << argv0base << ": error adding the virtual user:\n  "
+	     << resp.msg << endl;
+      exit(1);
+    }
+  }
+  else {
+    ferr << argv0base << ": error: user '" << user << "' already exists."
+	 << endl;
+    exit(1);
+  }
+}
+
+void add_alias(mystring user, mystring alias)
+{
+  alias = alias.lower();
+  user = user.lower();
+  if(!domain.exists(alias)) {
+    vpwentry vpw(alias, "*", 0, user);
+    vpw.set_defaults(true, true);
+    response resp = domain.set(&vpw, true);
+    if(!resp)
+      if(!o_quiet)
+	ferr << argv0base << ": warning: adding the alias '"
+	     << alias
+	     << "' failed:\n  "
+	     << resp.msg << endl;
+    else
+      if(!o_quiet)
+	fout << argv0base << ": alias '" << alias << "' successfully added"
+	     << endl;
+  }
+  else
+    if(!o_quiet)
+      ferr << argv0base << ": warning: alias '" << alias << "' already exists."
+	   << endl;
+}
+
+void set_defaults()
+{
+  if(!strcmp(argv0base, "vaddalias"))
+    o_domailbox = false;
+  if(!o_hardquota)
+    o_hardquota = config->default_hardquota();
+  if(!o_softquota)
+    o_softquota = config->default_softquota();
+  if(!o_msgsize)
+    o_msgsize = config->default_msgsize();
+  if(!o_msgcount)
+    o_msgcount = config->default_msgcount();
+  if(!o_expiry)
+    o_expiry = config->default_expiry();
+  if(o_expiry != -1)
+    o_expiry += time(0);
+}
+
+int cli_main(int argc, char* argv[])
+{
+  if(!go_home())
+    return 1;
+
+  set_defaults();
+  
+  add_user(argv[0]);
+  if(!o_quiet)
+    fout << argv0base << ": user '" << argv[0] << "' successfully added"
+	 << endl;
+  
+  for(int i = 1; i < argc; i++)
+    add_alias(argv[0], argv[i]);
+  
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vadduser.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,137 @@
+<HTML>
+<HEAD>
+<TITLE>vadduser - Add a user to a virtual domain</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vadduser - Add a user to a virtual domain
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vadduser</STRONG>
+[<STRONG>-c INT</STRONG>] [<STRONG>--msgcount=INT</STRONG>] [<STRONG>-D</STRONG>] [<STRONG>--no-mailbox</STRONG>] [<STRONG>-d STR</STRONG>] [<STRONG>--directory=STR</STRONG>] [<STRONG>-e INT</STRONG>] [<STRONG>--expiry=INT</STRONG>] [<STRONG>-f STR</STRONG>] [<STRONG>--forward=STR</STRONG>] [<STRONG>-P</STRONG>] [<STRONG>--no-password</STRONG>] [<STRONG>-p STR</STRONG>] [<STRONG>--personal=STR</STRONG>] [<STRONG>-Q INT</STRONG>] [<STRONG>--hardquota=INT</STRONG>] [<STRONG>-q INT</STRONG>] [<STRONG>--softquota=INT</STRONG>] [<STRONG>--quiet</STRONG>] [<STRONG>-z INT</STRONG>] [<STRONG>--msgsize=INT</STRONG>]
+<EM>USERNAME [ALIAS1 ...]\n"
+"or vaddalias [-f ADDRESS] USERNAME [ALIAS1 ...]</EM>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program is used to set up a user within a virtual host. If this
+program is reading from a tty, it will then ask for a password (twice, to
+make sure you typed it in correctly), otherwise it will read the password
+from the input with no prompting. It will then add the user to the virtual
+password table in the current directory and create a mail directory for the
+new user. It will also add an entry for each of the named aliases.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__c">-c INT, --msgcount=INT</A></STRONG><DD>
+<P>
+Set the user's message count limit.
+
+<DT><STRONG><A NAME="item__D_">-D, --no-mailbox</A></STRONG><DD>
+<P>
+Do not create a mailbox for this user. Defaults to true for vaddalias.
+
+<DT><STRONG><A NAME="item__d">-d STR, --directory=STR</A></STRONG><DD>
+<P>
+Set the path to the user's mailbox. Note that this directory is
+unconditionally prefixed with ``./''.
+
+<DT><STRONG><A NAME="item__e">-e INT, --expiry=INT</A></STRONG><DD>
+<P>
+Set the account's expiry time (in seconds).
+
+<DT><STRONG><A NAME="item__f">-f STR, --forward=STR</A></STRONG><DD>
+<P>
+Add a forwarding address to this user (this may be used multiple times).
+
+<DT><STRONG><A NAME="item__P_">-P, --no-password</A></STRONG><DD>
+<P>
+Do not ask for a password, and instead set the pass phrase field to an
+unusable value.
+
+<DT><STRONG><A NAME="item__p">-p STR, --personal=STR</A></STRONG><DD>
+<P>
+Set the user's personal information.
+
+<DT><STRONG><A NAME="item__Q">-Q INT, --hardquota=INT</A></STRONG><DD>
+<P>
+Set the user's hard quota (in bytes).
+
+<DT><STRONG><A NAME="item__q">-q INT, --softquota=INT</A></STRONG><DD>
+<P>
+Set the user's soft quota (in bytes).
+
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+<DT><STRONG><A NAME="item__z">-z INT, --msgsize=INT</A></STRONG><DD>
+<P>
+Set the user's message size limit (in bytes).
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+0 if all steps were successful, non-zero otherwise. If any of the steps
+fail, a diagnostic message is printed.
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vsetup(1)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+You must have either created the users subdirectory by hand or run the
+<EM>vsetup</EM> program before using this program.
+
+<P>
+This program expects the environment variable <CODE>HOME</CODE> to be set, and executes a change directory to the contents of it before
+starting. It is also required that you change user to the domain owner
+before using these utilities.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vadduser.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,125 @@
+=head1 NAME
+
+vadduser - Add a user to a virtual domain
+
+=head1 SYNOPSIS
+
+B<vadduser>
+[B<-c INT>]
+[B<--msgcount=INT>]
+[B<-D>]
+[B<--no-mailbox>]
+[B<-d STR>]
+[B<--directory=STR>]
+[B<-e INT>]
+[B<--expiry=INT>]
+[B<-f STR>]
+[B<--forward=STR>]
+[B<-P>]
+[B<--no-password>]
+[B<-p STR>]
+[B<--personal=STR>]
+[B<-Q INT>]
+[B<--hardquota=INT>]
+[B<-q INT>]
+[B<--softquota=INT>]
+[B<--quiet>]
+[B<-z INT>]
+[B<--msgsize=INT>]
+I<USERNAME [ALIAS1 ...]\n"
+"or vaddalias [-f ADDRESS] USERNAME [ALIAS1 ...]>
+
+=head1 DESCRIPTION
+
+This program is used to set up a user within a virtual host.
+If this program is reading from a tty,
+it will then ask for a password (twice, to make sure you typed it in
+correctly), otherwise it will read the password from the input with no
+prompting.
+It will then
+add the user to the virtual password table in the current
+directory and create a mail directory for the new user.
+It will also add an entry for each of the named aliases.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-c INT>, B<--msgcount=INT>
+
+Set the user's message count limit.
+
+=item B<-D>, B<--no-mailbox>
+
+Do not create a mailbox for this user. Defaults to true for vaddalias.
+
+=item B<-d STR>, B<--directory=STR>
+
+Set the path to the user's mailbox. Note that this directory is unconditionally prefixed with "./".
+
+=item B<-e INT>, B<--expiry=INT>
+
+Set the account's expiry time (in seconds).
+
+=item B<-f STR>, B<--forward=STR>
+
+Add a forwarding address to this user (this may be used multiple times).
+
+=item B<-P>, B<--no-password>
+
+Do not ask for a password, and instead set the pass phrase field to an unusable value.
+
+=item B<-p STR>, B<--personal=STR>
+
+Set the user's personal information.
+
+=item B<-Q INT>, B<--hardquota=INT>
+
+Set the user's hard quota (in bytes).
+
+=item B<-q INT>, B<--softquota=INT>
+
+Set the user's soft quota (in bytes).
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=item B<-z INT>, B<--msgsize=INT>
+
+Set the user's message size limit (in bytes).
+
+=back
+
+=head1 RETURN VALUE
+
+
+0 if all steps were successful, non-zero otherwise.
+If any of the steps fail, a diagnostic message is printed.
+
+
+
+=head1 SEE ALSO
+
+
+vsetup(1)
+
+
+
+=head1 NOTES
+
+You must have either created the users subdirectory by hand or run the
+F<vsetup> program before using this program.
+
+This program expects the environment variable C<HOME> to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vaddusers.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,158 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+#include "misc/pwcrypt.h"
+#include "config/configrc.h"
+#include "cli/cli.h"
+#include "vcommand.h"
+
+const char* cli_program = "vaddusers";
+const char* cli_help_prefix = "Add users to a virtual domain\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+
+static int o_quiet = false;
+
+// This program is used to set up a list of users within a virtual host.
+// The list is taken from standard input.
+// Each line in the list contains the user name, pass phrase, and an
+// optional list of aliases, all seperated by whitespace.
+// It will attempt to add each listed user to the virtual password table
+// and to create a mail directory for the new user, as well as attempting
+// to add entries for each of the named aliases.
+// If any step fails, the remainder of that line is ignored and
+// processing continues.
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+// NOTES
+//
+// You must have either created the users subdirectory by hand or run the
+// F<vsetup> program before using this program.
+//
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.  It
+// is also required that you change user to the domain owner before using
+// these utilities.
+
+// SEE ALSO
+//
+// vadduser(1), vsetup(1)
+
+static int errors = 0;
+
+mystring get_word(mystring& line)
+{
+  unsigned i = 0;
+  while(i < line.length() && isspace(line[i]))
+    ++i;
+  unsigned start = i;
+  while(i < line.length() && !isspace(line[i]))
+    ++i;
+  mystring word = line.sub(start, i-start);
+  line = line.right(i);
+  return word;
+}
+  
+void add_one(const mystring& line)
+{
+  mystring str = line;
+  mystring user = get_word(str);
+  mystring pass = get_word(str);
+  if(!user || !pass) {
+    errors++;
+    if(!o_quiet)
+      ferr << "vaddusers: invalid line, ignoring:\n  "
+	   << line << endl;
+    return;
+  }
+  user = user.lower();
+  if(domain.exists(user)) {
+    errors++;
+    if(!o_quiet)
+      ferr << "vaddusers: error: user '" << user
+	   << "' already exists, skipping.\n";
+    return;
+  }
+  {
+    mystring maildir = domain.userdir(user);
+    vpwentry vpw(user, pwcrypt(pass), maildir, 0);
+    vpw.set_defaults(true, true);
+    response resp = domain.set(&vpw, true, maildir);
+    if(!resp) {
+      errors++;
+      if(!o_quiet)
+	ferr << "vaddusers: error adding the virtual user, skipping aliases:\n  "
+	     << resp.msg << endl;
+      return;
+    }
+  }
+  if(!o_quiet)
+    fout << "added user '" << user << "'";
+  for(;;) {
+    mystring alias = get_word(str);
+    if(!alias)
+      break;
+    alias = alias.lower();
+    if(domain.exists(alias)) {
+      fout << endl;
+      errors++;
+      if(!o_quiet)
+	ferr << "vaddusers: warning: alias '" << alias
+	     << "' already exists, skipping." << endl;
+      continue;
+    }
+    vpwentry vpw(alias, "*", 0, user);
+    vpw.set_defaults(true, true);
+    response resp = domain.set(&vpw, true);
+    if(!resp) {
+      fout << endl;
+      errors++;
+      if(!o_quiet)
+	ferr << "vaddusers: warning: adding the alias '" << alias
+	     << "' failed:\n  " << resp.msg << endl;
+    }
+    if(!o_quiet)
+      fout << ", alias '" << alias << "'";
+  }
+  fout << endl;
+}
+
+int cli_main(int, char*[])
+{
+  if(!go_home())
+    return 1;
+  mystring line;
+  while(fin.getline(line))
+    add_one(line);
+  if(errors) {
+    if(!o_quiet)
+      ferr << "vaddusers: " << errors << " errors were encountered." << endl;
+    return 1;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchattr.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,281 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VCHATTR 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vchattr \- Changes the attributes on one or more virtual users
+.SH "SYNOPSIS"
+\fBvchattr\fR
+[\fB\-c\fR]
+[\fB--msgcount\fR]
+[\fB\-e\fR]
+[\fB--expiry\fR]
+[\fB\-E\fR]
+[\fB--enabled\fR]
+[\fB\-p\fR]
+[\fB--personal\fR]
+[\fB\-q\fR]
+[\fB--softquota\fR]
+[\fB\-Q\fR]
+[\fB--hardquota\fR]
+[\fB--quiet\fR]
+[\fB\-z\fR]
+[\fB--msgsize\fR]
+\fIVALUE USERNAME ...\fR
+.SH "DESCRIPTION"
+This program changes the value of one attribute on a set of virtual
+users.  It cannot be used to change the user's password or forwarding
+addresses -- use \fBvpasswd\fR and \fBvchforwards\fR to accomplish those
+tasks.
+.SH "OPTIONS"
+.Ip "\fB\-c\fR, \fB--msgcount\fR" 8
+Set the user's message count limit.
+.Ip "\fB\-e\fR, \fB--expiry\fR" 8
+Set the account's expiry time (in seconds).
+.Ip "\fB\-E\fR, \fB--enabled\fR" 8
+Enable (\f(CW1\fR) or disable (\f(CW0\fR) delivery to the virtual user's mailbox directory.  This does not delete the mailbox or any of the messages contained in or, nor prevent the user from logging in.
+.Ip "\fB\-p\fR, \fB--personal\fR" 8
+Set the user's personal information.
+.Ip "\fB\-q\fR, \fB--softquota\fR" 8
+Set the user's soft quota (in bytes).
+.Ip "\fB\-Q\fR, \fB--hardquota\fR" 8
+Set the user's hard quota (in bytes).
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.Ip "\fB\-z\fR, \fB--msgsize\fR" 8
+Set the user's message size limit (in bytes).
+.SH "RETURN VALUE"
+0 if the given attribute was successfully changed for all users,
+non-zero otherwise.
+If any of the steps fail, a diagnostic message is printed.
+.SH "SEE ALSO"
+\fIvadduser\fR\|(1)
+.SH "NOTES"
+This program expects the environment variable \f(CWHOME\fR to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VCHATTR 1"
+.IX Name "vchattr - Changes the attributes on one or more virtual users"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB\-c\fR, \fB--msgcount\fR"
+
+.IX Item "\fB\-e\fR, \fB--expiry\fR"
+
+.IX Item "\fB\-E\fR, \fB--enabled\fR"
+
+.IX Item "\fB\-p\fR, \fB--personal\fR"
+
+.IX Item "\fB\-q\fR, \fB--softquota\fR"
+
+.IX Item "\fB\-Q\fR, \fB--hardquota\fR"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Item "\fB\-z\fR, \fB--msgsize\fR"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "SEE ALSO"
+
+.IX Header "NOTES"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchattr.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,113 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "fdbuf/fdbuf.h"
+#include <stdlib.h>
+#include "mystring/mystring.h"
+#include "misc/passwdfn.h"
+#include "config/configrc.h"
+#include "cli/cli.h"
+#include "vcommand.h"
+
+const char* cli_program = "vchattr";
+const char* cli_help_prefix = "Changes the attributes on one or more virtual users\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "VALUE USERNAME ...";
+const int cli_args_min = 2;
+const int cli_args_max = -1;
+
+static int o_attr = 0;
+static int o_quiet = false;
+
+// This program changes the value of one attribute on a set of virtual
+// users.  It cannot be used to change the user's password or forwarding
+// addresses -- use B<vpasswd> and B<vchforwards> to accomplish those
+// tasks.
+
+cli_option cli_options[] = {
+  { 'c', "msgcount", cli_option::flag, vdomain::ATTR_MSGCOUNT, &o_attr,
+    "Set the user's message count limit", 0 },
+  { 'e', "expiry", cli_option::flag, vdomain::ATTR_EXPIRY, &o_attr,
+    "Set the account's expiry time (in seconds)", 0 },
+  { 'E', "enabled", cli_option::flag, vdomain::ATTR_MAILBOX_ENABLED, &o_attr,
+    "Enable or disable delivery to the account's mailbox", 0 },
+  // Enable (C<1>) or disable (C<0>) delivery to the virtual user's mailbox
+  // directory.  This does not delete the mailbox or any of the messages
+  // contained in or, nor prevent the user from logging in.
+  { 'p', "personal", cli_option::flag, vdomain::ATTR_PERSONAL, &o_attr,
+    "Set the user's personal information", 0 },
+  { 'q', "softquota", cli_option::flag, vdomain::ATTR_SOFTQUOTA, &o_attr,
+    "Set the user's soft quota (in bytes)", 0 },
+  { 'Q', "hardquota", cli_option::flag, vdomain::ATTR_HARDQUOTA, &o_attr,
+    "Set the user's hard quota (in bytes)", 0 },
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  { 'z', "msgsize", cli_option::flag, vdomain::ATTR_MSGSIZE, &o_attr,
+    "Set the user's message size limit (in bytes)", 0 },
+  {0}
+};
+
+// RETURN VALUE
+//
+// 0 if the given attribute was successfully changed for all users,
+// non-zero otherwise.
+// If any of the steps fail, a diagnostic message is printed.
+
+// SEE ALSO
+//
+// vadduser(1)
+
+// NOTES
+//
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.  It
+// is also required that you change user to the domain owner before using
+// these utilities.
+
+int cli_main(int argc, char* argv[])
+{
+  if(!o_attr) {
+    if(!o_quiet)
+      ferr << "vchattr: Must select an attribute to change." << endl;
+    return 1;
+  }
+  
+  if(!go_home())
+    return 1;
+
+  mystring value = argv[0];
+  unsigned errors = 0;
+
+  for(int i = 1; i < argc; i++) {
+    mystring username = argv[i];
+    username = username.lower();
+    
+    response resp = domain.chattr(username, o_attr, value);
+
+    if(!resp) {
+      if(!o_quiet)
+	ferr << "vchattr: error changing the attribute for user '"
+	     << username << "':\n  " << resp.msg << endl;
+      errors++;
+    }
+    else
+      if(!o_quiet)
+	fout << "vchattr: attribute for user '" << username
+	     << "' successfully changed." << endl;
+  }
+  return errors;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchattr.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,117 @@
+<HTML>
+<HEAD>
+<TITLE>vchattr - Changes the attributes on one or more virtual users</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vchattr - Changes the attributes on one or more virtual users
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vchattr</STRONG>
+[<STRONG>-c</STRONG>] [<STRONG>--msgcount</STRONG>] [<STRONG>-e</STRONG>] [<STRONG>--expiry</STRONG>] [<STRONG>-E</STRONG>] [<STRONG>--enabled</STRONG>] [<STRONG>-p</STRONG>] [<STRONG>--personal</STRONG>] [<STRONG>-q</STRONG>] [<STRONG>--softquota</STRONG>] [<STRONG>-Q</STRONG>] [<STRONG>--hardquota</STRONG>] [<STRONG>--quiet</STRONG>] [<STRONG>-z</STRONG>] [<STRONG>--msgsize</STRONG>]
+<EM>VALUE USERNAME ...</EM>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program changes the value of one attribute on a set of virtual users.
+It cannot be used to change the user's password or forwarding addresses --
+use <STRONG>vpasswd</STRONG> and <STRONG>vchforwards</STRONG> to accomplish those tasks.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__c_">-c, --msgcount</A></STRONG><DD>
+<P>
+Set the user's message count limit.
+
+<DT><STRONG><A NAME="item__e_">-e, --expiry</A></STRONG><DD>
+<P>
+Set the account's expiry time (in seconds).
+
+<DT><STRONG><A NAME="item__E_">-E, --enabled</A></STRONG><DD>
+<P>
+Enable (<CODE>1</CODE>) or disable (<CODE>0</CODE>) delivery to the virtual user's mailbox directory. This does not delete
+the mailbox or any of the messages contained in or, nor prevent the user
+from logging in.
+
+<DT><STRONG><A NAME="item__p_">-p, --personal</A></STRONG><DD>
+<P>
+Set the user's personal information.
+
+<DT><STRONG><A NAME="item__q_">-q, --softquota</A></STRONG><DD>
+<P>
+Set the user's soft quota (in bytes).
+
+<DT><STRONG><A NAME="item__Q_">-Q, --hardquota</A></STRONG><DD>
+<P>
+Set the user's hard quota (in bytes).
+
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+<DT><STRONG><A NAME="item__z_">-z, --msgsize</A></STRONG><DD>
+<P>
+Set the user's message size limit (in bytes).
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+0 if the given attribute was successfully changed for all users, non-zero
+otherwise. If any of the steps fail, a diagnostic message is printed.
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vadduser(1)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+This program expects the environment variable <CODE>HOME</CODE> to be set, and executes a change directory to the contents of it before
+starting. It is also required that you change user to the domain owner
+before using these utilities.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchattr.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,100 @@
+=head1 NAME
+
+vchattr - Changes the attributes on one or more virtual users
+
+=head1 SYNOPSIS
+
+B<vchattr>
+[B<-c>]
+[B<--msgcount>]
+[B<-e>]
+[B<--expiry>]
+[B<-E>]
+[B<--enabled>]
+[B<-p>]
+[B<--personal>]
+[B<-q>]
+[B<--softquota>]
+[B<-Q>]
+[B<--hardquota>]
+[B<--quiet>]
+[B<-z>]
+[B<--msgsize>]
+I<VALUE USERNAME ...>
+
+=head1 DESCRIPTION
+
+This program changes the value of one attribute on a set of virtual
+users.  It cannot be used to change the user's password or forwarding
+addresses -- use B<vpasswd> and B<vchforwards> to accomplish those
+tasks.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-c>, B<--msgcount>
+
+Set the user's message count limit.
+
+=item B<-e>, B<--expiry>
+
+Set the account's expiry time (in seconds).
+
+=item B<-E>, B<--enabled>
+
+Enable (C<1>) or disable (C<0>) delivery to the virtual user's mailbox directory.  This does not delete the mailbox or any of the messages contained in or, nor prevent the user from logging in.
+
+=item B<-p>, B<--personal>
+
+Set the user's personal information.
+
+=item B<-q>, B<--softquota>
+
+Set the user's soft quota (in bytes).
+
+=item B<-Q>, B<--hardquota>
+
+Set the user's hard quota (in bytes).
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=item B<-z>, B<--msgsize>
+
+Set the user's message size limit (in bytes).
+
+=back
+
+=head1 RETURN VALUE
+
+
+0 if the given attribute was successfully changed for all users,
+non-zero otherwise.
+If any of the steps fail, a diagnostic message is printed.
+
+
+
+=head1 SEE ALSO
+
+
+vadduser(1)
+
+
+
+=head1 NOTES
+
+
+This program expects the environment variable C<HOME> to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vcheckquota.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,258 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VCHECKQUOTA 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vcheckquota \- vmailmgr quota enforcement program
+.SH "SYNOPSIS"
+\fBvcheckquota\fR
+[\fB\-a UINT\fR]
+[\fB--soft-maxsize=UINT\fR]
+[\fB\-m STR\fR]
+[\fB--soft-message=STR\fR]
+.SH "DESCRIPTION"
+\fIvcheckquota\fR ensures that the hard and soft quotas are enforced,
+that message counts and sizes are appropriately limited.
+The limits are set by the vadduser or vchattr command.
+.PP
+The following rules are applied:
+.Ip "1" 8
+If the message is larger than the message size limit, it is rejected.
+.Ip "2" 8
+If the user has too many messages in their mailbox,
+further messages are rejected.
+.Ip "3" 8
+If the user is over their hard quota, all further messages are rejected
+and no warning messages are linked in.
+.Ip "4" 8
+If the user is over their soft quota, and the message is small
+(as defined by \fIsoft-maxsize\fR), the message is accepted, otherwise
+it is rejected.  If \fIsoft-message\fR is defined, a warning message
+is linked into the mailbox in either case.
+.PP
+Warning: the soft-message is linked into the users maildir once for each
+message that is received while the account is over its soft quota.  This may
+result in multiple warning messages.
+.SH "OPTIONS"
+.Ip "\fB\-a \s-1UINT\s0\fR, \fB--soft-maxsize=\s-1UINT\s0\fR" 8
+The maximum message size after soft quota is reached. Defaults to 4096.
+.Ip "\fB\-m \s-1STR\s0\fR, \fB--soft-message=\s-1STR\s0\fR" 8
+The path to the soft quota warning message. Defaults to no message.
+.SH "SEE ALSO"
+\fIvadduser\fR\|(1), \fIvchattr\fR\|(1)
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VCHECKQUOTA 1"
+.IX Name "vcheckquota - vmailmgr quota enforcement program"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "1"
+
+.IX Item "2"
+
+.IX Item "3"
+
+.IX Item "4"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB\-a \s-1UINT\s0\fR, \fB--soft-maxsize=\s-1UINT\s0\fR"
+
+.IX Item "\fB\-m \s-1STR\s0\fR, \fB--soft-message=\s-1STR\s0\fR"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vcheckquota.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,236 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include "config/configrc.h"
+#include "cli/cli.h"
+#include "fdbuf/fdbuf.h"
+#include "vcommand.h"
+#include "ac/dirent.h"
+#include "misc/itoa.h"
+#include "misc/stat_fns.h"
+#include "misc/md5.h"
+#include "misc/strtou.h"
+#include "misc/utoa.h"
+
+const char* cli_program = "vcheckquota";
+const char* cli_help_prefix = "vmailmgr quota enforcement program\n";
+const char* cli_help_suffix = "
+Warning: the soft-message is linked into the users maildir once for each
+message that is received while the account is over its soft quota.  This may
+result in multiple warning messages.\n";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+static unsigned soft_maxsize = 4096;
+static const char* soft_message = 0;
+
+// F<vcheckquota> ensures that the hard and soft quotas are enforced,
+// that message counts and sizes are appropriately limited.
+// The limits are set by the vadduser or vchattr command.
+//
+// The following rules are applied:
+//
+// =over 8
+//
+// =item 1
+//
+// If the message is larger than the message size limit, it is rejected.
+//
+// =item 2
+//
+// If the user has too many messages in their mailbox,
+// further messages are rejected.
+//
+// =item 3
+//
+// If the user is over their hard quota, all further messages are rejected
+// and no warning messages are linked in.
+//
+// =item 4
+//
+// If the user is over their soft quota, and the message is small
+// (as defined by I<soft-maxsize>), the message is accepted, otherwise
+// it is rejected.  If I<soft-message> is defined, a warning message
+// is linked into the mailbox in either case.
+//
+// =back
+
+cli_option cli_options[] = {
+  { 'a', "soft-maxsize", cli_option::uinteger, 0, &soft_maxsize,
+    "The maximum message size after soft quota is reached", "4096" },
+  { 'm', "soft-message", cli_option::string, 0, &soft_message,
+    "The path to the soft quota warning message", "no message" },
+  {0}
+};
+
+// SEE ALSO
+//
+// vadduser(1), vchattr(1)
+
+void exit_msg(const char* msg, int code)
+{
+  fout << "vcheckquota: " << msg << endl;
+  exit(code);
+}
+void die_fail(const char* msg) { exit_msg(msg, 100); }
+void die_temp(const char* msg) { exit_msg(msg, 111); }
+
+bool stat_dir(const mystring& dirname, unsigned& count, unsigned long& size) {
+  struct stat buf;
+  DIR* dir = opendir(dirname.c_str());
+  if(!dir) 
+    die_temp("Could not maildir\n");
+
+  while(dirent* entry = readdir(dir)) {
+    const char* name = entry->d_name;
+    if(name[0] == '.' &&
+       (NAMLEN(entry) == 1 ||
+	(name[1] == '.' && NAMLEN(entry) == 2)))
+      continue;
+
+    mystring fullname = dirname + "/" + name;
+
+    if(stat(fullname.c_str(), &buf) == -1) {
+      fout << "Cannot stat " << fullname.c_str() << "\n";
+      return false;
+    }
+
+    if(S_ISREG(buf.st_mode)) {
+      ++count;
+      size += buf.st_blocks * 512;
+    }
+  }
+  closedir(dir);
+  return true;
+}
+
+void link_softquota_message(const mystring& mailbox)
+{
+  mystring newdir = mailbox + "/new/";
+  pid_t pid = getpid();
+  for(;;) {
+    mystring path = newdir + itoa(time(0)) + ".";
+    path = path + itoa(pid) + ".softquota-warning";
+    if(symlink(soft_message, path.c_str()) == 0)
+      return;
+    if(errno != EEXIST)
+      die_temp("Could not create symlink to soft quota warning message");
+    sleep(1);
+  }
+}
+
+void check_quota(mystring mailbox,
+		 unsigned hardquota, unsigned softquota,
+		 unsigned maxsize, unsigned maxcount)
+{
+  /*
+   * There are 4 cases to consider when comparing disk useage (du)
+   * agains hard and soft quotas:
+   *
+   * Case 1: soft = 0, hard = 0: user has no quota set
+   * Case 2: soft = 0, hard > 0: use hard quota
+   * Case 3: soft > 0, hard = 0: treat soft quota as hard
+   * Case 4: soft > 0, hard > 0: if du becomes larger
+   *         then soft quota, allow message in if 
+   *         a) it is small (<2048 bytes), 
+   *         b) it would not put du over hard quota.
+   */
+
+
+  //compute message size
+  struct stat st;
+  if(fstat(0, &st) == -1)
+    die_temp("Failed to stat message");
+ 
+  unsigned long msgsize = st.st_blocks * 512;
+
+  if(maxsize != UINT_MAX && msgsize > maxsize)
+    //message is too large
+    die_fail("Sorry, this message is larger than the current maximum message size limit.\n");
+
+  /* Case 1: no quotas set */
+  if(softquota == UINT_MAX && hardquota == UINT_MAX && maxcount == UINT_MAX)
+    return;
+
+  mystring dirname = mailbox;
+  mystring newdir  = dirname + "/new";
+  mystring curdir  = dirname + "/cur";
+  unsigned cur_count=0;
+  unsigned long cur_size=0;
+  unsigned new_count=0;
+  unsigned long new_size=0;
+
+  //treat stat_dir failures as temp errors
+  if(!stat_dir(newdir, new_count, new_size))
+    die_temp("Failed to stat new dir");
+  if(!stat_dir(curdir, cur_count, cur_size))
+    die_temp("Failed to stat cur dir");
+
+  unsigned long du  = cur_size  + new_size  + msgsize;
+  unsigned msgcount = cur_count + new_count + 1;
+
+  //too many messages in the mbox
+  if(maxcount != UINT_MAX && msgcount > maxcount)
+    die_fail("Sorry, the person you sent this message has too many messages stored in the mailbox\n");
+
+  // No total size quotas are set
+  if(hardquota == UINT_MAX)
+    if(softquota == UINT_MAX)
+      return;
+  // Take care of Cases 2 and 3, and make everything look like Case 4
+    else
+      hardquota = softquota;
+  
+  // Check hard quota before soft quota, as it has priority
+  if(du > hardquota) 
+    die_fail("Message would exceed virtual user's disk quota.\n");
+  
+  // Soft quota allows small (4K default) messages
+  // In other words, it only blocks large messages
+  if(du > softquota) {
+    if(soft_message)
+      link_softquota_message(mailbox);
+    if(msgsize > soft_maxsize)
+      die_fail("Sorry, your message cannot be delivered.\n"
+	       "User's disk quota exceeded.\n"
+	       "A small message will be delivered should you wish "
+	       "to inform this person.\n");
+  }
+}
+
+int cli_main(int, char**)
+{
+#define ENV_VAR_REQ(VAR,ENV) const char* tmp__##VAR = getenv(#ENV); if(!tmp__##VAR) die_fail(#ENV " is not set");
+#define ENV_VAR_STR(VAR,ENV) ENV_VAR_REQ(VAR,ENV) mystring VAR = tmp__##VAR;
+#define ENV_VAR_UINT(VAR,ENV) ENV_VAR_REQ(VAR,ENV) unsigned VAR = strtou(tmp__##VAR, &tmp__##VAR); if(*tmp__##VAR) die_fail(#ENV " is not a valid number");
+
+  ENV_VAR_STR(maildir,  MAILDIR);
+  // Always succeed for aliases.
+  if(!maildir) 
+    return 0;
+
+  ENV_VAR_UINT(maxsize,   VUSER_MSGSIZE);
+  ENV_VAR_UINT(maxcount,  VUSER_MSGCOUNT);
+  ENV_VAR_UINT(hardquota, VUSER_HARDQUOTA);
+  ENV_VAR_UINT(softquota, VUSER_SOFTQUOTA);
+
+  check_quota(maildir, hardquota, softquota, maxsize, maxcount);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vcheckquota.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,100 @@
+<HTML>
+<HEAD>
+<TITLE>vcheckquota - vmailmgr quota enforcement program</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vcheckquota - vmailmgr quota enforcement program
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vcheckquota</STRONG>
+[<STRONG>-a UINT</STRONG>] [<STRONG>--soft-maxsize=UINT</STRONG>] [<STRONG>-m STR</STRONG>] [<STRONG>--soft-message=STR</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+<EM>vcheckquota</EM> ensures that the hard and soft quotas are enforced, that message counts and
+sizes are appropriately limited. The limits are set by the vadduser or
+vchattr command.
+
+<P>
+The following rules are applied:
+
+<OL>
+<LI>
+<P>
+If the message is larger than the message size limit, it is rejected.
+
+<LI>
+<P>
+If the user has too many messages in their mailbox, further messages are
+rejected.
+
+<LI>
+<P>
+If the user is over their hard quota, all further messages are rejected and
+no warning messages are linked in.
+
+<LI>
+<P>
+If the user is over their soft quota, and the message is small (as defined
+by <EM>soft-maxsize</EM>), the message is accepted, otherwise it is rejected. If <EM>soft-message</EM> is defined, a warning message is linked into the mailbox in either case.
+
+</OL>
+<P>
+Warning: the soft-message is linked into the users maildir once for each
+message that is received while the account is over its soft quota. This may
+result in multiple warning messages.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__a">-a UINT, --soft-maxsize=UINT</A></STRONG><DD>
+<P>
+The maximum message size after soft quota is reached. Defaults to 4096.
+
+<DT><STRONG><A NAME="item__m">-m STR, --soft-message=STR</A></STRONG><DD>
+<P>
+The path to the soft quota warning message. Defaults to no message.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vadduser(1),</CODE> <CODE>vchattr(1)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vcheckquota.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,78 @@
+=head1 NAME
+
+vcheckquota - vmailmgr quota enforcement program
+
+=head1 SYNOPSIS
+
+B<vcheckquota>
+[B<-a UINT>]
+[B<--soft-maxsize=UINT>]
+[B<-m STR>]
+[B<--soft-message=STR>]
+
+
+=head1 DESCRIPTION
+
+F<vcheckquota> ensures that the hard and soft quotas are enforced,
+that message counts and sizes are appropriately limited.
+The limits are set by the vadduser or vchattr command.
+
+The following rules are applied:
+
+=over 8
+
+=item 1
+
+If the message is larger than the message size limit, it is rejected.
+
+=item 2
+
+If the user has too many messages in their mailbox,
+further messages are rejected.
+
+=item 3
+
+If the user is over their hard quota, all further messages are rejected
+and no warning messages are linked in.
+
+=item 4
+
+If the user is over their soft quota, and the message is small
+(as defined by I<soft-maxsize>), the message is accepted, otherwise
+it is rejected.  If I<soft-message> is defined, a warning message
+is linked into the mailbox in either case.
+
+=back
+
+
+
+Warning: the soft-message is linked into the users maildir once for each
+message that is received while the account is over its soft quota.  This may
+result in multiple warning messages.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-a UINT>, B<--soft-maxsize=UINT>
+
+The maximum message size after soft quota is reached. Defaults to 4096.
+
+=item B<-m STR>, B<--soft-message=STR>
+
+The path to the soft quota warning message. Defaults to no message.
+
+=back
+
+=head1 SEE ALSO
+
+
+vadduser(1), vchattr(1)
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchforwards.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,226 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VCHFORWARDS 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vchforwards \- Change virtual user forwarding addresses.
+.SH "SYNOPSIS"
+\fBvchforwards\fR
+[\fB--quiet\fR]
+\fIUSERNAME [DESTINATION1 ...]\fR
+.SH "DESCRIPTION"
+This program replaces the virtual user's list of forwarding addresses
+with the given list.
+.PP
+If no forwarding addresses are given, forwarding is disabled.
+.SH "OPTIONS"
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "SEE ALSO"
+\fIvmailmgr\fR\|(7)
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VCHFORWARDS 1"
+.IX Name "vchforwards - Change virtual user forwarding addresses."
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchforwards.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,94 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+#include "config/configrc.h"
+#include "cli/cli.h"
+#include "vcommand.h"
+
+const char* cli_program = "vchforwards";
+const char* cli_help_prefix =
+"Change virtual user forwarding addresses.\n";
+const char* cli_help_suffix =
+"If no forwarding addresses are given, forwarding is disabled.
+";
+const char* cli_args_usage = "USERNAME [DESTINATION1 ...]";
+const int cli_args_min = 1;
+const int cli_args_max = -1;
+
+static int o_quiet = false;
+
+// This program replaces the virtual user's list of forwarding addresses
+// with the given list.
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+// SEE ALSO
+//
+// vmailmgr(7)
+
+int cli_main(int argc, char* argv[])
+{
+  if(!go_home())
+    return 1;
+
+  mystring username = argv[0];
+  username = username.lower();
+  
+  vpwentry* vpw = domain.lookup(username, false);
+  if(!vpw) {
+    if(!o_quiet)
+      ferr << "vchforwards: User '" << username << "' does not exist." << endl;
+    return 1;
+  }
+
+  for(int i = 1; i < argc; i++) {
+    response resp1 = domain.validate_forward(argv[i]);
+    if(!resp1) {
+      if(!o_quiet)
+	ferr << "vchforwards: error with forwarding address '" << argv[i]
+	     << "':\n  " << resp1.msg << endl;
+      return 1;
+    }
+  }
+  
+  if(argc > 1) {
+    mystring dest = argv[1];
+    for(int i = 2; i < argc; i++)
+      dest = dest + mystring::NUL + argv[i];
+    vpw->forwards = dest;
+  }
+  else
+    vpw->forwards = 0;
+
+  response resp2 = domain.set(vpw, false);
+  if(!resp2) {
+    if(!o_quiet)
+      ferr << "vchforwards: Could not change user '" << username << "':\n"
+	"  " << resp2.msg << endl;
+    return 1;
+  }
+  if(!o_quiet)
+    fout << "vchforwards: User '" << username << "' successfully changed."
+	 << endl;
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchforwards.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,72 @@
+<HTML>
+<HEAD>
+<TITLE>vchforwards - Change virtual user forwarding addresses.</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vchforwards - Change virtual user forwarding addresses.
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vchforwards</STRONG>
+[<STRONG>--quiet</STRONG>]
+<EM>USERNAME [DESTINATION1 ...]</EM>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program replaces the virtual user's list of forwarding addresses with
+the given list.
+
+<P>
+If no forwarding addresses are given, forwarding is disabled.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vmailmgr(7)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vchforwards.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,41 @@
+=head1 NAME
+
+vchforwards - Change virtual user forwarding addresses.
+
+=head1 SYNOPSIS
+
+B<vchforwards>
+[B<--quiet>]
+I<USERNAME [DESTINATION1 ...]>
+
+=head1 DESCRIPTION
+
+This program replaces the virtual user's list of forwarding addresses
+with the given list.
+
+
+If no forwarding addresses are given, forwarding is disabled.
+
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 SEE ALSO
+
+
+vmailmgr(7)
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vcommand.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,42 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "vcommand.h"
+#include "fdbuf/fdbuf.h"
+
+extern const char* cli_program;
+
+bool go_home()
+{
+  if(!user.home) {
+    ferr << cli_program << ": Can't determine home directory" << endl;
+    return false;
+  }
+  if(chdir(user.home.c_str()) == -1) {
+    ferr << cli_program << ": Can't change to home directory" << endl;
+    return false;
+  }
+  config = &domain.config;
+  password_file = config->password_file();
+  return true;
+}
+
+pwentry user;
+vdomain domain(user);
+mystring password_file;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vcommand.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,11 @@
+#ifndef VMAILMGR__V_COMMAND__H__
+#define VMAILMGR__V_COMMAND__H__
+
+#include "vdomain/vdomain.h"
+
+extern bool go_home();
+extern vdomain domain;
+extern mystring password_file;
+extern pwentry user;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vconf2dir	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,31 @@
+#!/bin/sh
+set -e
+if [ $# -ne 2 ]; then
+  echo Usage: vconf2dir configuration-file configuration-dir
+  exit 1
+fi
+
+sed -e '/^#/d' -e '/^ *$/d' -e '/=/!d' -e 's/ *= */ /' <"$1" | \
+{
+  if ! cd "$2"; then
+    echo vconf2dir: "$2" is not a directory.
+    exit 1
+  fi
+  while read n v; do
+    echo "$v" > $n
+  done
+}
+
+cd "$2"
+# Post-process postmaster-aliases
+if [ -f postmaster-aliases ]; then
+  pa=`cat postmaster-aliases`
+  echo -n >postmaster-aliases
+  i=1
+  v=`echo $pa | cut -d, -f$i`
+  while [ -n "$v" ]; do
+    echo $v >>postmaster-aliases
+    i=`expr $i + 1`
+    v=`echo $pa | cut -d, -f$i`
+  done
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeliver.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,270 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VDELIVER 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vdeliver \- VMailMgr delivery agent
+.SH "SYNOPSIS"
+\fBvdeliver\fR
+[\fB\-D\fR]
+[\fB\-F\fR]
+[\fB\-R\fR]
+[\fB\-d\fR]
+[\fB\-f\fR]
+[\fB--quiet\fR]
+[\fB\-r\fR]
+.SH "DESCRIPTION"
+vdeliver is the unified e-mail message delivery agent for virtual
+domains managed by vmailmgr.
+It is run from the \fI.qmail-default\fR file, and automatically handles
+delivery to any user within a virtual domain.
+.SH "OPTIONS"
+.Ip "\fB\-D\fR" 8
+Add the \f(CWReturn-Path:\fR line to the top of the message. (default)
+.Ip "\fB\-F\fR" 8
+Add a \*(L"\f(CWFrom \fR\*(R" mailbox line.
+.Ip "\fB\-R\fR" 8
+Add a \*(L"\f(CWReturn-Path:\fR\*(R" line (default).
+.Ip "\fB\-d\fR" 8
+Do not add the \f(CWDelivered-To:\fR line to the top of the message.
+.Ip "\fB\-f\fR" 8
+Do not add the \f(CWFrom\fR mailbox line to the top of the message. Note that this line is never added when the message is being re-injected into the mail stream. (default)
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.Ip "\fB\-r\fR" 8
+Do not add the \f(CWReturn-Path:\fR line to the top of the message.
+.SH "RETURN VALUE"
+Returns 0 if delivery was successful,
+100 if a fatal error occurred,
+or 111 if a temporary error occurred.
+.SH "ENVIRONMENT"
+\fIvdeliver\fR expects to be run by \fIqmail-local\fR as it requires several
+of the environment variables that it sets.
+See the \fIqmail-command\fR(8) manual page for full details on these
+variables.
+In particular, it requires \f(CWDTLINE\fR, \f(CWEXT\fR, \f(CWHOST\fR, \f(CWRPLINE\fR,
+\f(CWSENDER\fR, \f(CWUFLINE\fR, and \f(CWUSER\fR.
+.SH "SEE ALSO"
+\fIcheckvpw\fR\|(1), \fIqmail-command\fR(8)
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VDELIVER 1"
+.IX Name "vdeliver - VMailMgr delivery agent"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB\-D\fR"
+
+.IX Item "\fB\-F\fR"
+
+.IX Item "\fB\-R\fR"
+
+.IX Item "\fB\-d\fR"
+
+.IX Item "\fB\-f\fR"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Item "\fB\-r\fR"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "ENVIRONMENT"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeliver.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,349 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "ac/time.h"
+#include "ac/wait.h"
+#include <signal.h>
+#include "fdbuf/fdbuf.h"
+#include "cli/cli.h"
+#include "vcommand.h"
+#include "misc/itoa.h"
+#include "misc/stat_fns.h"
+#include "misc/exec.h"
+
+const char* cli_program = "vdeliver";
+const char* cli_help_prefix = "VMailMgr delivery agent\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+static int addufline = false;
+static int addrpline = true;
+static int adddtline = true;
+static int o_quiet = false;
+
+// vdeliver is the unified e-mail message delivery agent for virtual
+// domains managed by vmailmgr.
+// It is run from the F<.qmail-default> file, and automatically handles
+// delivery to any user within a virtual domain.
+
+cli_option cli_options[] = {
+  { 'D', 0, cli_option::flag, true, &adddtline,
+    "Add a \"Delivered-To:\" line (default)", 0 },
+  // Add the C<Return-Path:> line to the top of the message. (default)
+  { 'F', 0, cli_option::flag, true, &addufline,
+    "Add a \"From \" mailbox line", 0 },
+  { 'R', 0, cli_option::flag, true, &addrpline,
+    "Add a \"Return-Path:\" line (default)", 0 },
+  { 'd', 0, cli_option::flag, false, &adddtline,
+    "Do not add the \"Delivered-To:\" line", 0 },
+  //Do not add the C<Delivered-To:> line to the top of the message.
+  { 'f', 0, cli_option::flag, false, &addufline,
+    "Do not add the \"From \" mailbox line (default)", 0 },
+  // Do not add the C<From> mailbox line to the top of the message.
+  // Note that this line is never added when the message is being
+  // re-injected into the mail stream. (default)
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  { 'r', 0, cli_option::flag, false, &addrpline,
+    "Do not add the \"Return-Path:\" line", 0 },
+  // Do not add the C<Return-Path:> line to the top of the message.
+  {0}
+};
+
+// RETURN VALUE
+//
+// Returns 0 if delivery was successful,
+// 100 if a fatal error occurred,
+// or 111 if a temporary error occurred.
+
+// ENVIRONMENT
+//
+// F<vdeliver> expects to be run by F<qmail-local> as it requires several
+// of the environment variables that it sets.
+// See the I<qmail-command>(8) manual page for full details on these
+// variables.
+// In particular, it requires C<DTLINE>, C<EXT>, C<HOST>, C<RPLINE>,
+// C<SENDER>, C<UFLINE>, and C<USER>.
+
+// SEE ALSO
+//
+// checkvpw(1), I<qmail-command>(8)
+
+#ifndef HAVE_GETHOSTNAME
+int gethostname(char *name, size_t len);
+#endif
+
+const char* make_hostname()
+{
+  static char buf[512];
+  gethostname(buf, 511);
+  return buf;
+}
+
+void exit_msg(const char* msg, int code)
+{
+  if(!o_quiet)
+    fout << "vdeliver: " << msg << endl;
+  exit(code);
+}
+
+void exit_msg(const char* msg1, const mystring& msg2, int code)
+{
+  if(!o_quiet)
+    fout << "vdeliver: " << msg1 << msg2 << endl;
+  exit(code);
+}
+
+void die_fail(const char* msg) { exit_msg(msg, 100); }
+void die_temp(const char* msg) { exit_msg(msg, 111); }
+
+void fail_quota()
+{
+  die_fail("Delivery failed due to system quota violation");
+}
+
+mystring read_me()
+{
+  static mystring me;
+  static mystring mefilename = config->qmail_root() + "control/me";
+  if(!me) {
+    fdibuf in(mefilename.c_str());
+    if(in)
+      in.getline(me);
+  }
+  if(!me)
+    die_temp("control/me is empty!");
+  return me;
+}
+
+char* ufline;
+char* rpline;
+char* dtline;
+
+bool dump(fdobuf& out, bool dosync)
+{
+  if((ufline && !out.write(ufline, strlen(ufline))) ||
+     (rpline && !out.write(rpline, strlen(rpline))) ||
+     (dtline && !out.write(dtline, strlen(dtline))) ||
+     !fin.rewind() ||
+     !fdbuf_copy(fin, out)) {
+    out.close();
+    return false;
+  }
+  if(dosync && !out.sync())
+    return false;
+  if(!out.close())
+    return false;
+  return true;
+}
+
+static mystring partname;
+static mystring maildir;
+
+void deliver_partial()
+{
+  const mystring newdir = maildir + "/new";
+  const mystring tmpdir = maildir + "/tmp";
+
+  if(!is_dir(tmpdir.c_str()) || !is_dir(newdir.c_str()))
+    die_temp("Destination directory does not appear to be a maildir.");
+
+  const mystring hostname = make_hostname();
+  pid_t pid = getpid();
+  for(;; sleep(2)) {
+    partname = "/" + mystring(itoa(time(0))) + "." + itoa(pid)
+      + "." + hostname;
+    
+    mystring newfile = newdir + partname;
+    mystring tmpfile = tmpdir + partname;
+
+    if(is_exist(tmpfile.c_str()))
+      continue;
+    else {
+      fdobuf out(tmpfile.c_str(), fdobuf::create | fdobuf::excl, 0600);
+      if(!out) {
+#ifdef EDQUOT
+	if(out.error_number() == EDQUOT)
+	  fail_quota();
+#endif
+	continue;
+      }
+      if(!dump(out, true)) {
+#ifdef EDQUOT
+	if(out.error_number() == EDQUOT)
+	  fail_quota();
+#endif
+	die_temp("Error writing the output file.");
+      }
+      return;
+    }
+  }
+}
+
+void deliver_fail(const char* msg)
+{
+  mystring tmpfile = maildir + "/tmp/" + partname;
+  unlink(tmpfile.c_str());
+  die_temp(msg);
+}
+
+void deliver_final()
+{
+  mystring tmpfile = maildir + "/tmp/" + partname;
+  mystring newfile = maildir + "/new/" + partname;
+  
+  if(link(tmpfile.c_str(), newfile.c_str()))
+    deliver_fail("Error linking the temp file to the new file.");
+  if(unlink(tmpfile.c_str()))
+    deliver_fail("Error unlinking the temp file.");
+}
+
+void write_envelope(fdobuf& out,
+		    mystring sender, mystring recipient, mystring host)
+{
+  out << 'F' << sender << '\0';
+
+  for(mystring_iter iter = recipient; iter; ++iter) {
+    mystring r = *iter;
+    int at = r.find_first('@');
+    out << 'T' << r;
+
+    // If the address has no '@', add the virtual domain
+    if(at < 0)
+      out << '@' << host;
+    // If it has an '@', but no domain, add the local domain
+    else if((unsigned)at == r.length()-1)
+      out << read_me();
+    // Else, nothing to add, address already copied
+    out << '\0';
+  }
+  out << '\0';
+}
+
+void inject(mystring sender, mystring recip, mystring host)
+{
+  int pipe1[2];
+  int pipe2[2];
+  if(pipe(pipe1) || pipe(pipe2))
+    deliver_fail("System call to 'pipe' failed.");
+
+  mystring qq = config->qmail_root() + "bin/qmail-queue";
+  pid_t pid;
+  switch(pid = fork()) {
+  case -1:
+    deliver_fail("System call to 'fork' failed.");
+  case 0:
+    close(pipe1[1]);
+    close(pipe2[1]);
+    if((dup2(pipe1[0], 0) != 0) || (dup2(pipe2[0], 1) != 1))
+      exit(111);
+    execl(qq.c_str(), qq.c_str(), 0);
+    die_temp("Exec of qmail-queue failed.");
+  default:
+    close(pipe1[0]);
+    close(pipe2[0]);
+    signal(SIGPIPE, SIG_IGN);
+    ufline = 0;
+    rpline = 0;
+    fdobuf out(pipe1[1], true);
+    if(!dump(out, false))
+      deliver_fail("Error writing to pipe");
+    fdobuf env(pipe2[1], true);
+    write_envelope(env, sender, recip, host);
+    if(!env.flush() || !env.close())
+      deliver_fail("Error sending envelope to pipe");
+    int status;
+    if(waitpid(pid, &status, WUNTRACED) != pid)
+      deliver_fail("System call to 'waitpid' failed.");
+    if(!WIFEXITED(status))
+      deliver_fail("qmail-queue crashed!");
+    if(WEXITSTATUS(status))
+      deliver_fail("qmail-queue exited with an error!");
+  }
+}
+
+void enqueue(mystring recipient, mystring host, mystring sender)
+{
+  int f = sender.find_first('@');
+  if(f > 0) {
+    presetenv("QMAILUSER=", sender.left(f));
+    presetenv("QMAILHOST=", sender.right(f+1));
+  }
+  inject(sender, recipient, host);
+}
+
+int cli_main(int, char*[])
+{
+  if(!go_home())
+    return 1;
+  
+#define ENV_VAR(VAR,ENV) const char* tmp__##VAR = getenv(#ENV); if(!tmp__##VAR) die_fail(#ENV " is not set"); mystring VAR = tmp__##VAR;
+  ENV_VAR(user, USER);
+  ENV_VAR(ext, EXT);
+  ENV_VAR(host, HOST);
+  ENV_VAR(sender, SENDER);
+#undef ENV_VAR
+#define ENV_VAR(VAR,ENV) VAR = getenv(#ENV); if(!VAR) die_fail(#ENV " is not set");
+  ENV_VAR(ufline, UFLINE);
+  ENV_VAR(rpline, RPLINE);
+  ENV_VAR(dtline, DTLINE);
+#undef ENV_VAR
+
+  if(!addufline)
+    ufline = 0;
+  if(!addrpline)
+    rpline = 0;
+  if(!adddtline)
+    dtline = 0;
+
+  vpwentry* vpw = domain.lookup(ext, false);
+  if(!vpw)
+    die_fail(mystring("Invalid or unknown virtual user '" + ext + "'").c_str());
+  if(vpw->expiry < (unsigned)time(0))
+    die_fail(mystring("Virtual user '" + ext + "' has expired").c_str());
+  
+  vpw->export_env();
+  bool enabled = vpw->is_mailbox_enabled && !!vpw->mailbox;
+
+  int r = execute("vdeliver-predeliver");
+  if(r)
+    exit_msg("Execution of vdeliver-predeliver failed", r);
+
+  if(enabled) {
+    maildir = vpw->mailbox;
+    deliver_partial();
+  }
+  if(!!vpw->forwards)
+    enqueue(vpw->forwards, host, sender);
+  if(enabled)
+    deliver_final();
+
+  if(!fin.rewind()) {
+    if(!o_quiet)
+      fout << "Could not re-rewind standard input" << endl;
+  }
+  else if(execute("vdeliver-postdeliver"))
+    if(!o_quiet)
+      fout << "Execution of vdeliver-postdeliver failed" << endl;
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeliver.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,109 @@
+<HTML>
+<HEAD>
+<TITLE>vdeliver - VMailMgr delivery agent</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#ENVIRONMENT">ENVIRONMENT</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vdeliver - VMailMgr delivery agent
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vdeliver</STRONG>
+[<STRONG>-D</STRONG>] [<STRONG>-F</STRONG>] [<STRONG>-R</STRONG>] [<STRONG>-d</STRONG>] [<STRONG>-f</STRONG>] [<STRONG>--quiet</STRONG>] [<STRONG>-r</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+vdeliver is the unified e-mail message delivery agent for virtual domains
+managed by vmailmgr. It is run from the <EM>.qmail-default</EM> file, and automatically handles delivery to any user within a virtual
+domain.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__D">-D</A></STRONG><DD>
+<P>
+Add the <CODE>Return-Path:</CODE> line to the top of the message. (default)
+
+<DT><STRONG><A NAME="item__F">-F</A></STRONG><DD>
+<P>
+Add a ``<CODE>From </CODE>'' mailbox line.
+
+<DT><STRONG><A NAME="item__R">-R</A></STRONG><DD>
+<P>
+Add a ``<CODE>Return-Path:</CODE>'' line (default).
+
+<DT><STRONG><A NAME="item__d">-d</A></STRONG><DD>
+<P>
+Do not add the <CODE>Delivered-To:</CODE> line to the top of the message.
+
+<DT><STRONG><A NAME="item__f">-f</A></STRONG><DD>
+<P>
+Do not add the <CODE>From</CODE> mailbox line to the top of the message. Note that this line is never added
+when the message is being re-injected into the mail stream. (default)
+
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+<DT><STRONG><A NAME="item__r">-r</A></STRONG><DD>
+<P>
+Do not add the <CODE>Return-Path:</CODE> line to the top of the message.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+Returns 0 if delivery was successful, 100 if a fatal error occurred, or 111
+if a temporary error occurred.
+
+<P>
+<HR>
+<H1><A NAME="ENVIRONMENT">ENVIRONMENT</A></H1>
+<P>
+<EM>vdeliver</EM> expects to be run by <EM>qmail-local</EM> as it requires several of the environment variables that it sets. See the <EM>qmail-command</EM>(8) manual page for full details on these variables. In particular, it
+requires <CODE>DTLINE</CODE>, <CODE>EXT</CODE>, <CODE>HOST</CODE>, <CODE>RPLINE</CODE>,
+<CODE>SENDER</CODE>, <CODE>UFLINE</CODE>, and <CODE>USER</CODE>.
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>checkvpw(1),</CODE> <EM>qmail-command</EM>(8)
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeliver.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,90 @@
+=head1 NAME
+
+vdeliver - VMailMgr delivery agent
+
+=head1 SYNOPSIS
+
+B<vdeliver>
+[B<-D>]
+[B<-F>]
+[B<-R>]
+[B<-d>]
+[B<-f>]
+[B<--quiet>]
+[B<-r>]
+
+
+=head1 DESCRIPTION
+
+vdeliver is the unified e-mail message delivery agent for virtual
+domains managed by vmailmgr.
+It is run from the F<.qmail-default> file, and automatically handles
+delivery to any user within a virtual domain.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-D>
+
+Add the C<Return-Path:> line to the top of the message. (default)
+
+=item B<-F>
+
+Add a "C<From >" mailbox line.
+
+=item B<-R>
+
+Add a "C<Return-Path:>" line (default).
+
+=item B<-d>
+
+Do not add the C<Delivered-To:> line to the top of the message.
+
+=item B<-f>
+
+Do not add the C<From> mailbox line to the top of the message. Note that this line is never added when the message is being re-injected into the mail stream. (default)
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=item B<-r>
+
+Do not add the C<Return-Path:> line to the top of the message.
+
+=back
+
+=head1 RETURN VALUE
+
+
+Returns 0 if delivery was successful,
+100 if a fatal error occurred,
+or 111 if a temporary error occurred.
+
+
+
+=head1 ENVIRONMENT
+
+
+F<vdeliver> expects to be run by F<qmail-local> as it requires several
+of the environment variables that it sets.
+See the I<qmail-command>(8) manual page for full details on these
+variables.
+In particular, it requires C<DTLINE>, C<EXT>, C<HOST>, C<RPLINE>,
+C<SENDER>, C<UFLINE>, and C<USER>.
+
+
+
+=head1 SEE ALSO
+
+
+checkvpw(1), I<qmail-command>(8)
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeluser.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,249 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VDELUSER 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vdeluser \- Delete users from a virtual domain
+.SH "SYNOPSIS"
+\fBvdeluser\fR
+[\fB\-D\fR]
+[\fB--no-mailbox\fR]
+[\fB--quiet\fR]
+\fIUSER1 [USER2 ...]\fR
+.SH "DESCRIPTION"
+This program will take the steps necessary to
+remove a user from a virtual domain.
+.PP
+For each user listed on the command line, it does the following:
+.PP
+1. It removes the named user's entry from the local password file.
+.PP
+2. It removes any qmail delivery files that point to the named user's
+mail directory.
+.PP
+3. It removes the user's mail directory and all of its contents
+(recursively).
+.PP
+If any of the above steps fail, a warning is issued and processing
+continues.
+.SH "OPTIONS"
+.Ip "\fB\-D\fR, \fB--no-mailbox\fR" 8
+Do not delete users that have a mailbox.
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "NOTES"
+You must have either created the users subdirectory by hand or run the
+\fIvsetup\fR program before using this program.
+.PP
+This program expects the environment variable \f(CWHOME\fR to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VDELUSER 1"
+.IX Name "vdeluser - Delete users from a virtual domain"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB\-D\fR, \fB--no-mailbox\fR"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "NOTES"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeluser.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,91 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "fdbuf/fdbuf.h"
+#include "config/configrc.h"
+#include "cli/cli.h"
+#include "vcommand.h"
+
+const char* cli_program = "vdeluser";
+const char* cli_help_prefix = "Delete users from a virtual domain\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "USER1 [USER2 ...]";
+const int cli_args_min = 1;
+const int cli_args_max = -1;
+
+static int o_quiet = false;
+static int o_domailbox = true;
+
+// This program will take the steps necessary to
+// remove a user from a virtual domain.
+//
+// For each user listed on the command line, it does the following:
+//
+// 1. It removes the named user's entry from the local password file.
+//
+// 2. It removes any qmail delivery files that point to the named user's
+// mail directory.
+//
+// 3. It removes the user's mail directory and all of its contents
+// (recursively).
+//
+// If any of the above steps fail, a warning is issued and processing
+// continues.
+
+cli_option cli_options[] = {
+  { 'D', "no-mailbox", cli_option::flag, false, &o_domailbox,
+    "Do not delete users that have a mailbox", 0 },
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+// NOTES
+//
+// You must have either created the users subdirectory by hand or run the
+// F<vsetup> program before using this program.
+//
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.  It
+// is also required that you change user to the domain owner before using
+// these utilities.
+
+int cli_main(int argc, char* argv[])
+{
+  if(!go_home())
+    return 1;
+  int errors = 0;
+  for(int i = 0; i < argc; i++) {
+    response r = domain.deluser(argv[i], o_domailbox);
+    if(!r) {
+      errors++;
+      if(!o_quiet)
+	ferr << "vdeluser: error deleting user '" << argv[i] << "':\n  "
+	     << r.msg << endl;
+    }
+    else
+      if(!o_quiet)
+	fout << "vdeluser: user '" << argv[i] << "' successfully deleted."
+	     << endl;
+  }
+  if(errors) {
+    if(!o_quiet)
+      ferr << "vdeluser: " << errors << " errors were encountered." << endl;
+    return 1;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeluser.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,97 @@
+<HTML>
+<HEAD>
+<TITLE>vdeluser - Delete users from a virtual domain</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vdeluser - Delete users from a virtual domain
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vdeluser</STRONG>
+[<STRONG>-D</STRONG>] [<STRONG>--no-mailbox</STRONG>] [<STRONG>--quiet</STRONG>]
+<EM>USER1 [USER2 ...]</EM>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program will take the steps necessary to remove a user from a virtual
+domain.
+
+<P>
+For each user listed on the command line, it does the following:
+
+<P>
+1. It removes the named user's entry from the local password file.
+
+<P>
+2. It removes any qmail delivery files that point to the named user's mail
+directory.
+
+<P>
+3. It removes the user's mail directory and all of its contents
+(recursively).
+
+<P>
+If any of the above steps fail, a warning is issued and processing
+continues.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__D_">-D, --no-mailbox</A></STRONG><DD>
+<P>
+Do not delete users that have a mailbox.
+
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+You must have either created the users subdirectory by hand or run the
+<EM>vsetup</EM> program before using this program.
+
+<P>
+This program expects the environment variable <CODE>HOME</CODE> to be set, and executes a change directory to the contents of it before
+starting. It is also required that you change user to the domain owner
+before using these utilities.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vdeluser.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,62 @@
+=head1 NAME
+
+vdeluser - Delete users from a virtual domain
+
+=head1 SYNOPSIS
+
+B<vdeluser>
+[B<-D>]
+[B<--no-mailbox>]
+[B<--quiet>]
+I<USER1 [USER2 ...]>
+
+=head1 DESCRIPTION
+
+This program will take the steps necessary to
+remove a user from a virtual domain.
+
+For each user listed on the command line, it does the following:
+
+1. It removes the named user's entry from the local password file.
+
+2. It removes any qmail delivery files that point to the named user's
+mail directory.
+
+3. It removes the user's mail directory and all of its contents
+(recursively).
+
+If any of the above steps fail, a warning is issued and processing
+continues.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-D>, B<--no-mailbox>
+
+Do not delete users that have a mailbox.
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 NOTES
+
+
+You must have either created the users subdirectory by hand or run the
+F<vsetup> program before using this program.
+
+This program expects the environment variable C<HOME> to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,238 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VPASSWD 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vpasswd \- Changes the password for an individual virtual user
+.SH "SYNOPSIS"
+\fBvpasswd\fR
+[\fB--quiet\fR]
+\fIUSERNAME\fR
+.SH "DESCRIPTION"
+This program is used to change a user's password within a virtual
+domain.
+.SH "OPTIONS"
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "RETURN VALUE"
+0 if the password was changed successfully, nonzero otherwise.
+.SH "SEE ALSO"
+\fIcheckvpw\fR\|(1)
+.SH "NOTES"
+You must have either created the users subdirectory by hand or run the
+\fIvsetup\fR program before using this program.
+.PP
+This program expects the environment variable \f(CWHOME\fR to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VPASSWD 1"
+.IX Name "vpasswd - Changes the password for an individual virtual user"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "SEE ALSO"
+
+.IX Header "NOTES"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,88 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "fdbuf/fdbuf.h"
+#include <stdlib.h>
+#include "mystring/mystring.h"
+#include "misc/passwdfn.h"
+#include "config/configrc.h"
+#include "cli/cli.h"
+#include "vcommand.h"
+
+const char* cli_program = "vpasswd";
+const char* cli_help_prefix = "Changes the password for an individual virtual user\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "USERNAME";
+const int cli_args_min = 1;
+const int cli_args_max = 1;
+
+static int o_quiet = false;
+
+// This program is used to change a user's password within a virtual
+// domain.
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+// RETURN VALUE
+//
+// 0 if the password was changed successfully, nonzero otherwise.
+
+// SEE ALSO
+//
+// checkvpw(1)
+
+// NOTES
+//
+// You must have either created the users subdirectory by hand or run the
+// F<vsetup> program before using this program.
+//
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.  It
+// is also required that you change user to the domain owner before using
+// these utilities.
+
+int cli_main(int, char* argv[])
+{
+  if(!go_home())
+    return 1;
+
+  mystring username = argv[0];
+  username = username.lower();
+
+  mystring pass = getpasswd("vpasswd");
+  if(pass.length() == 0)
+    return 1;
+
+  response resp = domain.chattr(username, vdomain::ATTR_PASS, pass);
+
+  if(!resp) {
+    if(!o_quiet)
+      ferr << "vpasswd: error changing the password for user '"
+	   << username << "':\n  " << resp.msg << endl;
+    return 1;
+  }
+  else {
+    if(!o_quiet)
+      fout << "vpasswd: password for user '" << username
+	   << "' successfully changed." << endl;
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,88 @@
+<HTML>
+<HEAD>
+<TITLE>vpasswd - Changes the password for an individual virtual user</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vpasswd - Changes the password for an individual virtual user
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vpasswd</STRONG>
+[<STRONG>--quiet</STRONG>]
+<EM>USERNAME</EM>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program is used to change a user's password within a virtual domain.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+0 if the password was changed successfully, nonzero otherwise.
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>checkvpw(1)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+You must have either created the users subdirectory by hand or run the
+<EM>vsetup</EM> program before using this program.
+
+<P>
+This program expects the environment variable <CODE>HOME</CODE> to be set, and executes a change directory to the contents of it before
+starting. It is also required that you change user to the domain owner
+before using these utilities.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,57 @@
+=head1 NAME
+
+vpasswd - Changes the password for an individual virtual user
+
+=head1 SYNOPSIS
+
+B<vpasswd>
+[B<--quiet>]
+I<USERNAME>
+
+=head1 DESCRIPTION
+
+This program is used to change a user's password within a virtual
+domain.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 RETURN VALUE
+
+
+0 if the password was changed successfully, nonzero otherwise.
+
+
+
+=head1 SEE ALSO
+
+
+checkvpw(1)
+
+
+
+=head1 NOTES
+
+
+You must have either created the users subdirectory by hand or run the
+F<vsetup> program before using this program.
+
+This program expects the environment variable C<HOME> to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2cdb.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,220 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VPASSWD2CDB 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vpasswd2cdb \- Converts text password tables to CDB format
+.SH "SYNOPSIS"
+\fBvpasswd2cdb\fR
+[\fB--quiet\fR]
+.SH "DESCRIPTION"
+Reads in a standard virtual password table in the current directory,
+and writes it out to a CDB table.  The file names for the text and CDB
+tables are determined from the configuration file.
+.SH "OPTIONS"
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VPASSWD2CDB 1"
+.IX Name "vpasswd2cdb - Converts text password tables to CDB format"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2cdb.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,93 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <string.h>
+#include "cdb++/cdb++.h"
+#include "cli/cli.h"
+#include "config/configrc.h"
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+#include "vpwentry/vpwentry.h"
+#include "vcommand.h"
+
+const char* cli_program = "vpasswd2cdb";
+const char* cli_help_prefix = "Converts text password tables to CDB format\n";
+const char* cli_help_suffix =
+"Reads in a standard virtual password table in the current directory,
+and writes it out to a CDB table.  The file names for the text and CDB
+tables are determined from the configuration file.";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+
+static int o_quiet = false;
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+static bool getpw(fdibuf& in, vpwentry& out)
+{
+  mystring buf;
+  if(!in.getline(buf))
+    return false;
+
+  int first = buf.find_first(':');
+  if(first < 0) return false;
+
+  return out.from_record(buf.left(first), buf.c_str() + first);
+}
+
+int cli_main(int, char* [])
+{
+  if(!go_home())
+    return 1;
+
+  fdibuf in(password_file.c_str());
+  if(!in) {
+    if(!o_quiet)
+      ferr << "Can't open password table named '"
+	   << password_file << "'." << endl;
+    return 1;
+  }
+  mystring cdbname = password_file + ".cdb";
+  mystring cdbtmp = cdbname + ".tmp";
+  cdb_writer cdb(cdbtmp, 0600);
+  if(!cdb) {
+    if(!o_quiet)
+      ferr << "Can't open CDB temporary file named '" << cdbtmp << "'."
+	   << endl;
+    return 1;
+  }
+  vpwentry vpw;
+  while(getpw(in, vpw)) {
+    if(!cdb.put(vpw.name, vpw.to_record())) {
+      if(!o_quiet)
+	ferr << "Failed to add record to CDB table." << endl;
+      return 1;
+    }
+  }
+  if(!cdb.end(cdbname)) {
+    if(!o_quiet)
+      ferr << "Failed to finish CDB table into '"
+	   << password_file << ".cdb'." << endl;
+    return 1;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2cdb.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,60 @@
+<HTML>
+<HEAD>
+<TITLE>vpasswd2cdb - Converts text password tables to CDB format</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vpasswd2cdb - Converts text password tables to CDB format
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vpasswd2cdb</STRONG>
+[<STRONG>--quiet</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+Reads in a standard virtual password table in the current directory, and
+writes it out to a CDB table. The file names for the text and CDB tables
+are determined from the configuration file.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2cdb.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,33 @@
+=head1 NAME
+
+vpasswd2cdb - Converts text password tables to CDB format
+
+=head1 SYNOPSIS
+
+B<vpasswd2cdb>
+[B<--quiet>]
+
+
+=head1 DESCRIPTION
+
+
+
+Reads in a standard virtual password table in the current directory,
+and writes it out to a CDB table.  The file names for the text and CDB
+tables are determined from the configuration file.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2db.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,220 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VPASSWD2DB 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vpasswd2db \- Converts text password tables to current vpwtable DB format
+.SH "SYNOPSIS"
+\fBvpasswd2db\fR
+[\fB--quiet\fR]
+.SH "DESCRIPTION"
+Reads in a standard virtual password table in the current directory,
+and writes it out to a table.  The file names for the input and output
+tables are determined from the configuration file.
+.SH "OPTIONS"
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VPASSWD2DB 1"
+.IX Name "vpasswd2db - Converts text password tables to current vpwtable DB format"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2db.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,80 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <string.h>
+#include "cli/cli.h"
+#include "config/configrc.h"
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+#include "vpwentry/vpwentry.h"
+#include "vcommand.h"
+
+const char* cli_program = "vpasswd2db";
+const char* cli_help_prefix = "Converts text password tables to current vpwtable DB format\n";
+const char* cli_help_suffix =
+"Reads in a standard virtual password table in the current directory,
+and writes it out to a table.  The file names for the input and output
+tables are determined from the configuration file.";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+
+static int o_quiet = false;
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+static bool getpw(fdibuf& in, vpwentry& out)
+{
+  mystring buf;
+  if(!in.getline(buf))
+    return false;
+
+  int first = buf.find_first(':');
+  if(first < 0) return false;
+
+  return out.from_record(buf.left(first), buf.c_str() + first);
+}
+
+int cli_main(int, char* [])
+{
+  if(!go_home())
+    return 1;
+
+  fdibuf in(password_file.c_str());
+  if(!in) {
+    if(!o_quiet)
+      ferr << "Can't open password table named '"
+	   << password_file << "'." << endl;
+    return 1;
+  }
+
+  vpwtable* out = domain.table();
+
+  vpwentry vpw;
+  while(getpw(in, vpw)) {
+    if(!out->put(&vpw, true)) {
+      if(!o_quiet)
+	ferr << "Failed to add record to vpwtable." << endl;
+      return 1;
+    }
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2db.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,60 @@
+<HTML>
+<HEAD>
+<TITLE>vpasswd2db - Converts text password tables to current vpwtable DB format</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vpasswd2db - Converts text password tables to current vpwtable DB format
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vpasswd2db</STRONG>
+[<STRONG>--quiet</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+Reads in a standard virtual password table in the current directory, and
+writes it out to a table. The file names for the input and output tables
+are determined from the configuration file.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswd2db.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,33 @@
+=head1 NAME
+
+vpasswd2db - Converts text password tables to current vpwtable DB format
+
+=head1 SYNOPSIS
+
+B<vpasswd2db>
+[B<--quiet>]
+
+
+=head1 DESCRIPTION
+
+
+
+Reads in a standard virtual password table in the current directory,
+and writes it out to a table.  The file names for the input and output
+tables are determined from the configuration file.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswds.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,239 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VPASSWDS 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vpasswds \- Changes the passwords for a list of virtual users
+.SH "SYNOPSIS"
+\fBvpasswds\fR
+[\fB--quiet\fR]
+.SH "DESCRIPTION"
+This program is used to change the password of a list of virtual
+users.  The list is read from standard input.
+Each line in the list contains the user's name and new pass phrase,
+seperated by whitespace.
+It will attempt to change the password for each listed user.
+If any step fails, a warning is issued and processing continues with
+the next line.
+Any input folling the password is ignored.
+.SH "OPTIONS"
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "SEE ALSO"
+\fIvpasswd\fR\|(1)
+.SH "NOTES"
+You must have either created the users subdirectory by hand or run the
+\fIvsetup\fR program before using this program.
+.PP
+This program expects the environment variable \f(CWHOME\fR to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VPASSWDS 1"
+.IX Name "vpasswds - Changes the passwords for a list of virtual users"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "SEE ALSO"
+
+.IX Header "NOTES"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswds.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,122 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+#include "misc/response.h"
+#include "config/configrc.h"
+#include "cli/cli.h"
+#include "vcommand.h"
+
+const char* cli_program = "vpasswds";
+const char* cli_help_prefix = "Changes the passwords for a list of virtual users\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+
+static int o_quiet = false;
+
+// This program is used to change the password of a list of virtual
+// users.  The list is read from standard input.
+// Each line in the list contains the user's name and new pass phrase,
+// seperated by whitespace.
+// It will attempt to change the password for each listed user.
+// If any step fails, a warning is issued and processing continues with
+// the next line.
+// Any input folling the password is ignored.
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+// SEE ALSO
+//
+// vpasswd(1)
+
+// NOTES
+//
+// You must have either created the users subdirectory by hand or run the
+// F<vsetup> program before using this program.
+//
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.  It
+// is also required that you change user to the domain owner before using
+// these utilities.
+
+static int errors = 0;
+
+mystring get_word(mystring& line)
+{
+  unsigned i = 0;
+  while(i < line.length() && isspace(line[i]))
+    ++i;
+  unsigned start = i;
+  while(i < line.length() && !isspace(line[i]))
+    ++i;
+  mystring word = line.sub(start, i-start);
+  line = line.right(i);
+  return word;
+}
+  
+void change_one(const mystring& line)
+{
+  mystring str = line;
+  mystring user = get_word(str);
+  mystring pass = get_word(str);
+  if(!user || !pass) {
+    ++errors;
+    if(!o_quiet)
+      ferr << "vpasswds: invalid line, ignoring:\n  "
+	   << line << endl;
+    return;
+  }
+  user = user.lower();
+
+  response resp = domain.chattr(user, vdomain::ATTR_PASS, pass);
+
+  if(!resp) {
+    ++errors;
+    if(!o_quiet)
+      ferr << "vpasswds: error changing the password for user '"
+	   << user << "':\n  " << resp.msg << endl;
+    return;
+  }
+  else
+    if(!o_quiet)
+      fout << "vpasswds: password for user '" << user
+	   << "' successfully changed.\n";
+}
+
+int cli_main(int, char*[])
+{
+  if(!go_home())
+    return 1;
+  mystring str;
+  while(fin.getline(str))
+    change_one(str);
+  if(errors) {
+    if(!o_quiet)
+      ferr << "vpasswds: " << errors << " errors were encountered." << endl;
+    return 1;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswds.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,83 @@
+<HTML>
+<HEAD>
+<TITLE>vpasswds - Changes the passwords for a list of virtual users</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vpasswds - Changes the passwords for a list of virtual users
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vpasswds</STRONG>
+[<STRONG>--quiet</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program is used to change the password of a list of virtual users. The
+list is read from standard input. Each line in the list contains the user's
+name and new pass phrase, seperated by whitespace. It will attempt to
+change the password for each listed user. If any step fails, a warning is
+issued and processing continues with the next line. Any input folling the
+password is ignored.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vpasswd(1)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+You must have either created the users subdirectory by hand or run the
+<EM>vsetup</EM> program before using this program.
+
+<P>
+This program expects the environment variable <CODE>HOME</CODE> to be set, and executes a change directory to the contents of it before
+starting. It is also required that you change user to the domain owner
+before using these utilities.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpasswds.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,56 @@
+=head1 NAME
+
+vpasswds - Changes the passwords for a list of virtual users
+
+=head1 SYNOPSIS
+
+B<vpasswds>
+[B<--quiet>]
+
+
+=head1 DESCRIPTION
+
+This program is used to change the password of a list of virtual
+users.  The list is read from standard input.
+Each line in the list contains the user's name and new pass phrase,
+seperated by whitespace.
+It will attempt to change the password for each listed user.
+If any step fails, a warning is issued and processing continues with
+the next line.
+Any input folling the password is ignored.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 SEE ALSO
+
+
+vpasswd(1)
+
+
+
+=head1 NOTES
+
+
+You must have either created the users subdirectory by hand or run the
+F<vsetup> program before using this program.
+
+This program expects the environment variable C<HOME> to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpopbull.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,262 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VPOPBULL 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vpopbull \- Delivers pop bulletins to virtual users
+.SH "SYNOPSIS"
+\fBvpopbull\fR
+[\fB--quiet\fR]
+.SH "DESCRIPTION"
+Scans bulletin directories for any which are newer than the
+\&\fI.timestamp\fR file in the specified maildir.
+For each bulletin that it finds, it adds a symlink to that bulletin to
+the specified maildir.
+Since no reformatting is done, these bulletins must be fully formatted
+email messages, including full headers.
+.PP
+This program is designed to be run from \f(CWcheckvpw-postsetuid\fR.
+.SH "OPTIONS"
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "RETURN VALUE"
+Exits false if an error occurred during startup, true otherwise.
+.SH "ENVIRONMENT"
+This program expects the environment variable \f(CWHOME\fR to be set, and
+executes a change directory to the contents of it before starting.
+.PP
+This program expects \f(CWMAILDIR\fR to be set, and delivers any bulletins
+that it finds into this maildir.
+.PP
+If \f(CWVUSER\fR is set, a local bulletin directory is searched as above.
+.SH "FILES"
+The following control files are used:
+.Ip "\fIglobal-bulletin-dir\fR" 8
+This specifies the bulletin directory for all domains.
+.Ip "\fIbulletin-dir\fR" 8
+This specifies the bulletin (sub)directory for virtual domains.
+.SH "SEE ALSO"
+\fIvmailmgr\fR\|(7),
+\fIcheckvpw\fR\|(8),
+configuration.html
+.SH "NOTES"
+If either the global or local bulletin directories do not exist, they
+are silently ignored without failing.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VPOPBULL 1"
+.IX Name "vpopbull - Delivers pop bulletins to virtual users"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "ENVIRONMENT"
+
+.IX Header "FILES"
+
+.IX Item "\fIglobal-bulletin-dir\fR"
+
+.IX Item "\fIbulletin-dir\fR"
+
+.IX Header "SEE ALSO"
+
+.IX Header "NOTES"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpopbull.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,235 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "ac/dirent.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "ac/time.h"
+#include <unistd.h>
+#include "misc/itoa.h"
+#include "mystring/mystring.h"
+#include "config/configrc.h"
+//#include "misc/debug.h"
+#include "cli/cli.h"
+#include "fdbuf/fdbuf.h"
+#include "vcommand.h"
+
+const char* cli_program = "vpopbull";
+const char* cli_help_prefix = "Delivers pop bulletins to virtual users\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+
+static int o_quiet = false;
+
+// Scans bulletin directories for any which are newer than the
+// F<.timestamp> file in the specified maildir.
+// For each bulletin that it finds, it adds a symlink to that bulletin to
+// the specified maildir.
+// Since no reformatting is done, these bulletins must be fully formatted
+// email messages, including full headers.
+//
+// This program is designed to be run from C<checkvpw-postsetuid>.
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+// RETURN VALUE
+//
+// Exits false if an error occurred during startup, true otherwise.
+
+// ENVIRONMENT
+//
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.
+//
+// This program expects C<MAILDIR> to be set, and delivers any bulletins
+// that it finds into this maildir.
+//
+// If C<VUSER> is set, a local bulletin directory is searched as above.
+
+// FILES
+//
+// The following control files are used:
+//
+// =over 8
+//
+// =item F<global-bulletin-dir>
+//
+// This specifies the bulletin directory for all domains.
+//
+// =item F<bulletin-dir>
+//
+// This specifies the bulletin (sub)directory for virtual domains.
+//
+// =back
+
+// SEE ALSO
+//
+// vmailmgr(7),
+// checkvpw(8),
+// configuration.html
+
+// NOTES
+//
+// If either the global or local bulletin directories do not exist, they
+// are silently ignored without failing.
+
+#ifndef HAVE_GETHOSTNAME
+int gethostname(char *name, size_t len);
+#endif
+
+#define FATAL_FAILURES 0
+
+#if FATAL_FAILURES
+
+static void log(const mystring& msg)
+{
+  if(!o_quiet)
+    ferr << "vpopbull: " msg << endl;
+}
+
+#define FAIL(X) do{ log(X); return false; }while(0)
+
+#else
+
+#define FAIL(X) do{ return false; }while(0)
+
+#endif
+
+static bool make_link(const mystring& linkname, mystring dest)
+{
+  char host[128];
+  gethostname(host, sizeof host);
+  pid_t pid = getpid();
+  mystring destname;
+  dest += "/";
+  for(;;) {
+    time_t t = time(0);
+    destname = dest + itoa(t) + ".";
+    destname = destname + itoa(pid) + "." + host;
+    struct stat buf;
+    if(stat(destname.c_str(), &buf) == -1 && errno == ENOENT)
+      break;
+    sleep(2);
+  }
+  if(symlink(linkname.c_str(), destname.c_str()) == -1)
+    FAIL("Could not make symbolic link.");
+  return true;
+}
+
+static bool link_file(const mystring& bulldir,
+		      const mystring& filename,
+		      const mystring& destdir)
+{
+  mystring src;
+  if(bulldir[0] == '/')
+    // simple symbolic link
+    src = bulldir + "/" + filename;
+  else {
+    int i = -1;
+    while((i = destdir.find_first('/', i+1)) > 0)
+      src += "../";
+    src = src + bulldir + filename;
+  }
+  return make_link(src, destdir);
+}
+
+static time_t maildir_time;
+
+static time_t stat_mtime(const mystring& path)
+{
+  struct stat statbuf;
+  if(stat(path.c_str(), &statbuf) == -1)
+    return 0;
+  else
+    return statbuf.st_mtime;
+}
+
+static bool scan_file(const mystring& bulldir,
+		      const mystring& filename,
+		      const mystring& destdir)
+{
+  mystring fullname = bulldir + "/" + filename;
+  time_t mtime = stat_mtime(fullname);
+  if(!mtime)
+    FAIL("Can't stat bulletin '" + fullname + "'.");
+  if(maildir_time < mtime)
+    return link_file(bulldir, filename, destdir);
+  return true;
+}
+
+static bool scan_bulletins(const mystring& destdir, const mystring& bulldir)
+{
+  DIR* dir = opendir(bulldir.c_str());
+  // Do not fail if the directory does not exist.
+  if(!dir)
+    FAIL("Can't open bulletin directory '" + bulldir + "'.");
+  dirent* entry;
+  while((entry = readdir(dir)) != 0) {
+    if(entry->d_name[0] == '.')
+      continue;
+    if(!scan_file(bulldir, entry->d_name, destdir))
+      return false;
+  }
+  closedir(dir);
+  return true;
+}
+
+static void stat_maildir(const mystring& maildir)
+{
+  mystring timestamp = maildir + "/.timestamp";
+  maildir_time = stat_mtime(timestamp);
+  int fd = open(timestamp.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0600);
+  close(fd);
+}
+  
+static bool scan_bulletins(const mystring& maildir, bool non_virtual)
+{
+  stat_maildir(maildir);
+  mystring dir = maildir + "/new";
+#if FATAL_FAILURES
+  return scan_bulletins(dir, config->global_bulletin_dir()) &&
+    (non_virtual || scan_bulletins(dir, config->bulletin_dir()));
+#else
+  scan_bulletins(dir, config->global_bulletin_dir());
+  if(!non_virtual)
+    scan_bulletins(dir, config->bulletin_dir());
+  return true;
+#endif
+}
+
+int cli_main(int, char*[])
+{
+  if(!go_home())
+    return 1;
+  mystring maildir = getenv("MAILDIR");
+  if(!maildir) {
+    if(!o_quiet)
+      ferr << "vpopbull: MAILDIR is not set." << endl;
+    return 1;
+  }
+  mystring vuser = getenv("VUSER");
+  return scan_bulletins(maildir, !vuser) ? 0 : 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpopbull.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,118 @@
+<HTML>
+<HEAD>
+<TITLE>vpopbull - Delivers pop bulletins to virtual users</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#ENVIRONMENT">ENVIRONMENT</A>
+	<LI><A HREF="#FILES">FILES</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vpopbull - Delivers pop bulletins to virtual users
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vpopbull</STRONG>
+[<STRONG>--quiet</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+Scans bulletin directories for any which are newer than the
+<EM>.timestamp</EM> file in the specified maildir. For each bulletin that it finds, it adds a
+symlink to that bulletin to the specified maildir. Since no reformatting is
+done, these bulletins must be fully formatted email messages, including
+full headers.
+
+<P>
+This program is designed to be run from <CODE>checkvpw-postsetuid</CODE>.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+Exits false if an error occurred during startup, true otherwise.
+
+<P>
+<HR>
+<H1><A NAME="ENVIRONMENT">ENVIRONMENT</A></H1>
+<P>
+This program expects the environment variable <CODE>HOME</CODE> to be set, and executes a change directory to the contents of it before
+starting.
+
+<P>
+This program expects <CODE>MAILDIR</CODE> to be set, and delivers any bulletins that it finds into this maildir.
+
+<P>
+If <CODE>VUSER</CODE> is set, a local bulletin directory is searched as above.
+
+<P>
+<HR>
+<H1><A NAME="FILES">FILES</A></H1>
+<P>
+The following control files are used:
+
+<DL>
+<DT><STRONG><A NAME="item_global">global-bulletin-dir</A></STRONG><DD>
+<P>
+This specifies the bulletin directory for all domains.
+
+<DT><STRONG><A NAME="item_bulletin">bulletin-dir</A></STRONG><DD>
+<P>
+This specifies the bulletin (sub)directory for virtual domains.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vmailmgr(7),</CODE> <CODE>checkvpw(8),</CODE> configuration.html
+
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+If either the global or local bulletin directories do not exist, they are
+silently ignored without failing.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vpopbull.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,92 @@
+=head1 NAME
+
+vpopbull - Delivers pop bulletins to virtual users
+
+=head1 SYNOPSIS
+
+B<vpopbull>
+[B<--quiet>]
+
+
+=head1 DESCRIPTION
+
+Scans bulletin directories for any which are newer than the
+F<.timestamp> file in the specified maildir.
+For each bulletin that it finds, it adds a symlink to that bulletin to
+the specified maildir.
+Since no reformatting is done, these bulletins must be fully formatted
+email messages, including full headers.
+
+This program is designed to be run from C<checkvpw-postsetuid>.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 RETURN VALUE
+
+
+Exits false if an error occurred during startup, true otherwise.
+
+
+
+=head1 ENVIRONMENT
+
+
+This program expects the environment variable C<HOME> to be set, and
+executes a change directory to the contents of it before starting.
+
+This program expects C<MAILDIR> to be set, and delivers any bulletins
+that it finds into this maildir.
+
+If C<VUSER> is set, a local bulletin directory is searched as above.
+
+
+
+=head1 FILES
+
+
+The following control files are used:
+
+=over 8
+
+=item F<global-bulletin-dir>
+
+This specifies the bulletin directory for all domains.
+
+=item F<bulletin-dir>
+
+This specifies the bulletin (sub)directory for virtual domains.
+
+=back
+
+
+
+=head1 SEE ALSO
+
+
+vmailmgr(7),
+checkvpw(8),
+configuration.html
+
+
+
+=head1 NOTES
+
+
+If either the global or local bulletin directories do not exist, they
+are silently ignored without failing.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vrehash.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,242 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VREHASH 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vrehash \- Reorganize users directory\en"
+\*(L"Renames user directories in a virtual domain to match the current\en"
+\*(L"partitioning scheme
+.SH "SYNOPSIS"
+\fBvrehash\fR
+.SH "DESCRIPTION"
+This program is designed to be run after the sysadmin has changed the
+\f(CWuser-dir-bits\fR or \f(CWuser-dir-slices\fR configuration variables.
+It creates a new users directory called \f(CWnew.users\fR, where \f(CWusers\fR
+is the configured name of the user directory.
+It then traverses the password table, creates a new user directory name
+for each user, and moves the user's mail directory to the new
+directory name, creating any necessary directories as it goes.
+Any alias entries in the password table are copied as-is.
+.SH "RETURN VALUE"
+Returns 1 if any part of the process fails; 0 otherwise.
+.SH "NOTES"
+When the process is completed, a the old users directory will have
+been moved to \f(CWbackup.users\fR.
+If no errors occurred, you should be able to safely delete this
+directory and all its subdirectories.
+Check this directory first, though, to ensure that no important files
+remain.
+.SH "WARNINGS"
+This program is not particularly careful to clean up after itself if
+an error occurs.
+If an error occurs, you will have to check the status of the current
+directory, the virtual password file, and all the virtual users
+subdirectories in both \f(CWusers\fR and \f(CWnew.users\fR.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VREHASH 1"
+.IX Name "vrehash - Reorganize users directory\n"
+"Renames user directories in a virtual domain to match the current\n"
+"partitioning scheme"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "NOTES"
+
+.IX Header "WARNINGS"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vrehash.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,231 @@
+
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "misc/autodelete.h"
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+#include "misc/maildir.h"
+#include "config/configrc.h"
+#include "vpwentry/vpwentry.h"
+#include "vcommand.h"
+#include "misc/stat_fns.h"
+#include "cli/cli.h"
+#include "cdb++/cdb++.h"
+
+const char* cli_program = "vrehash";
+const char* cli_help_prefix = "Reorganize users directory\n"
+"Renames user directories in a virtual domain to match the current\n"
+"partitioning scheme\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+
+// This program is designed to be run after the sysadmin has changed the
+// C<user-dir-bits> or C<user-dir-slices> configuration variables.
+// It creates a new users directory called C<new.users>, where C<users>
+// is the configured name of the user directory.
+// It then traverses the password table, creates a new user directory name
+// for each user, and moves the user's mail directory to the new
+// directory name, creating any necessary directories as it goes.
+// Any alias entries in the password table are copied as-is.
+
+cli_option cli_options[] = {
+  {0}
+};
+
+// RETURN VALUE
+//
+// Returns 1 if any part of the process fails; 0 otherwise.
+
+// NOTES
+//
+// When the process is completed, a the old users directory will have
+// been moved to C<backup.users>.
+// If no errors occurred, you should be able to safely delete this
+// directory and all its subdirectories.
+// Check this directory first, though, to ensure that no important files
+// remain.
+
+// WARNINGS
+//
+// This program is not particularly careful to clean up after itself if
+// an error occurs.
+// If an error occurs, you will have to check the status of the current
+// directory, the virtual password file, and all the virtual users
+// subdirectories in both C<users> and C<new.users>.
+
+static cdb_reader* in = 0;
+static cdb_writer* out = 0;
+static mystring cdbfilename;
+static mystring tmpfilename;
+static mystring newuserdir;
+static mystring backupdir;
+
+mystring lock_dir()
+{
+  struct stat buf;
+  if(stat(".", &buf))
+    return "Error stat'ing the current directory ?!?";
+  if(buf.st_mode & S_ISVTX)
+    return "Directory is already locked";
+  if(chmod(".", buf.st_mode | S_ISVTX))
+    return "Can't lock directory";
+  cdbfilename = password_file + ".cdb";
+  tmpfilename = cdbfilename + ".tmp";
+  in = new cdb_reader(cdbfilename);
+  if(!*in)
+    return "Could not open virtual password table";
+  out = new cdb_writer(tmpfilename, 0600);
+  if(!*out)
+    return "Could not open temporary table exclusively";
+  return "";
+}
+
+mystring unlock_dir()
+{
+  struct stat buf;
+  if(stat(".", &buf))
+    return "Error stat'ing the current directory ?!?";
+  if(!(buf.st_mode & S_ISVTX))
+    return "Directory was not locked";
+  if(chmod(".", buf.st_mode & ~S_ISVTX))
+    return "Can't unlock directory";
+  if(out) {
+    if(out->end(cdbfilename)) {
+      delete out;
+      return "Error completing the virtual password table";
+    }
+    delete out;
+  }
+  delete in;
+  return "";
+}
+
+bool getvpwent(vpwentry& vpw)
+{
+  autodelete<datum> d = in->nextrec();
+  if(!d)
+    return false;
+  vpw.from_record(d->key, d->data);
+  return true;
+}
+
+mystring user_dir;
+
+mystring translate_one(vpwentry& vpw)
+{
+  mystring tmp = user_dir;
+  mystring newdir = "./" + newuserdir +
+		  domain.userdir(vpw.name).right(user_dir.length());
+  mystring vpwdir = "./" + domain.userdir(vpw.name);
+  mystring tmpdir = newdir.left(newdir.find_last('/'));
+  if(mkdirp(tmpdir.c_str(), 0755))
+    return "Error creating a user subdirectory: " + tmpdir;
+  if(rename(vpw.mailbox.c_str(), newdir.c_str()))
+    return "Error moving a user subdirectory." + vpw.mailbox;
+  vpw.mailbox = vpwdir;
+  return "";
+}
+
+mystring translate()
+{
+  vpwentry vpw;
+  unsigned errors = 0;
+  while(getvpwent(vpw)) {
+    if(!!vpw.mailbox) {
+      mystring response = translate_one(vpw);
+      if(!!response) {
+	ferr << "vrehash: " << response;
+	++errors;
+      }
+    }
+    if(!out->put(vpw.name, vpw.to_record())) {
+      return "vrehash: failed to add entry to table";
+      ++errors;
+    }
+  }
+  return "";
+}
+
+mystring renamedirs()
+{
+  if(rename(user_dir.c_str(), backupdir.c_str()) == -1)
+    return "Unable to make backup copy of user directory";
+  if(rename(newuserdir.c_str(), user_dir.c_str()) == -1)
+    return "Unable to rename new user directory";
+#if 0
+  if(rmdir(backupdir.c_str()) == -1)
+    return "Unable to remove backup user directory";
+#endif
+  return "";
+}
+
+bool check_ok(const char* msg, mystring (*fn)())
+{
+  fout << "vrehash: " << msg << ": ";
+  mystring status = fn();
+  if(!!status) {
+    fout << "failed:\n  " << status << endl;
+    return false;
+  }
+  else {
+    fout << "OK.\n";
+    return true;
+  }
+}
+
+int cli_main(int, char*[])
+{
+  if(!go_home())
+    return 1;
+
+  user_dir = config->user_dir();
+  
+  newuserdir = "new." + user_dir;
+  backupdir = "backup." + user_dir;
+
+  if(is_dir(newuserdir.c_str())) {
+    ferr << "vrehash: error: new users directory '" << newuserdir
+	 << "' already exists.\n";
+    return 1;
+  }
+  if(is_dir(backupdir.c_str())) {
+    ferr << "vrehash: error: backup directory '" << backupdir
+	 << "' already exists.\n";
+    return 1;
+  }
+  
+  if(!check_ok("locking directory", lock_dir))
+    return 1;
+
+  if(!check_ok("translating paths and making directories", translate))
+    return 1;
+
+  if(!check_ok("removing old user directory", renamedirs))
+    return 1;
+  
+  if(!check_ok("unlocking directory", unlock_dir))
+    return 1;
+  
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vrehash.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,85 @@
+<HTML>
+<HEAD>
+<TITLE>vrehash - Reorganize users directory\n"
+"Renames user directories in a virtual domain to match the current\n"
+"partitioning scheme</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#WARNINGS">WARNINGS</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vrehash - Reorganize users directory\n`` ''Renames user directories in a
+virtual domain to match the current\n`` ''partitioning scheme
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vrehash</STRONG>
+
+
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program is designed to be run after the sysadmin has changed the
+<CODE>user-dir-bits</CODE> or <CODE>user-dir-slices</CODE> configuration variables. It creates a new users directory called <CODE>new.users</CODE>, where <CODE>users</CODE>
+is the configured name of the user directory. It then traverses the
+password table, creates a new user directory name for each user, and moves
+the user's mail directory to the new directory name, creating any necessary
+directories as it goes. Any alias entries in the password table are copied
+as-is.
+
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+Returns 1 if any part of the process fails; 0 otherwise.
+
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+When the process is completed, a the old users directory will have been
+moved to <CODE>backup.users</CODE>. If no errors occurred, you should be able to safely delete this directory
+and all its subdirectories. Check this directory first, though, to ensure
+that no important files remain.
+
+<P>
+<HR>
+<H1><A NAME="WARNINGS">WARNINGS</A></H1>
+<P>
+This program is not particularly careful to clean up after itself if an
+error occurs. If an error occurs, you will have to check the status of the
+current directory, the virtual password file, and all the virtual users
+subdirectories in both <CODE>users</CODE> and <CODE>new.users</CODE>.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vrehash.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,57 @@
+=head1 NAME
+
+vrehash - Reorganize users directory\n"
+"Renames user directories in a virtual domain to match the current\n"
+"partitioning scheme
+
+=head1 SYNOPSIS
+
+B<vrehash>
+
+
+=head1 DESCRIPTION
+
+This program is designed to be run after the sysadmin has changed the
+C<user-dir-bits> or C<user-dir-slices> configuration variables.
+It creates a new users directory called C<new.users>, where C<users>
+is the configured name of the user directory.
+It then traverses the password table, creates a new user directory name
+for each user, and moves the user's mail directory to the new
+directory name, creating any necessary directories as it goes.
+Any alias entries in the password table are copied as-is.
+
+
+=head1 RETURN VALUE
+
+
+Returns 1 if any part of the process fails; 0 otherwise.
+
+
+
+=head1 NOTES
+
+
+When the process is completed, a the old users directory will have
+been moved to C<backup.users>.
+If no errors occurred, you should be able to safely delete this
+directory and all its subdirectories.
+Check this directory first, though, to ensure that no important files
+remain.
+
+
+
+=head1 WARNINGS
+
+
+This program is not particularly careful to clean up after itself if
+an error occurs.
+If an error occurs, you will have to check the status of the current
+directory, the virtual password file, and all the virtual users
+subdirectories in both C<users> and C<new.users>.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vsetup.1	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,240 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH VSETUP 1 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vsetup \- Sets up a virtual domain for its first use
+.SH "SYNOPSIS"
+\fBvsetup\fR
+[\fB--quiet\fR]
+.SH "DESCRIPTION"
+This program sets up the basic set of necessary files needed to use an
+account as a virtual domain with vmailmgr.
+The users directory is created if it does not exist.
+A \fI.qmail-default\fR file is created with the proper contents.
+If a \fI.qmail-default\fR previously existed, it is renamed to
+\&\fI.qmail-default~\fR.
+Three system aliases (\f(CWroot\fR, \f(CWmailer-daemon\fR, and \f(CWpostmaster\fR)
+are created to point to the configured postmaster.
+.SH "OPTIONS"
+.Ip "\fB--quiet\fR" 8
+Suppress all status messages.
+.SH "RETURN VALUE"
+0 if all files and directories are successfully created, 1 otherwise.
+.SH "SEE ALSO"
+\fIvdeliver\fR\|(1), \fIvmailmgrd\fR\|(8)
+.SH "NOTES"
+This program expects the environment variable \f(CWHOME\fR to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "VSETUP 1"
+.IX Name "vsetup - Sets up a virtual domain for its first use"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB--quiet\fR"
+
+.IX Header "RETURN VALUE"
+
+.IX Header "SEE ALSO"
+
+.IX Header "NOTES"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vsetup.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,174 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include "fdbuf/fdbuf.h"
+#include "config/configrc.h"
+#include "misc/stat_fns.h"
+#include "cli/cli.h"
+#include "misc/exec.h"
+#include "vcommand.h"
+
+const char* cli_program = "vsetup";
+const char* cli_help_prefix = "Sets up a virtual domain for its first use\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+
+static int o_quiet = false;
+
+// This program sets up the basic set of necessary files needed to use an
+// account as a virtual domain with vmailmgr.
+// The users directory is created if it does not exist.
+// A F<.qmail-default> file is created with the proper contents.
+// If a F<.qmail-default> previously existed, it is renamed to
+// F<.qmail-default~>.
+// Three system aliases (C<root>, C<mailer-daemon>, and C<postmaster>)
+// are created to point to the configured postmaster.
+
+cli_option cli_options[] = {
+  { 0, "quiet", cli_option::flag, true, &o_quiet,
+    "Suppress all status messages", 0 },
+  {0}
+};
+
+// RETURN VALUE
+//
+// 0 if all files and directories are successfully created, 1 otherwise.
+
+// SEE ALSO
+//
+// vdeliver(1), vmailmgrd(8)
+
+// NOTES
+//
+// This program expects the environment variable C<HOME> to be set, and
+// executes a change directory to the contents of it before starting.  It
+// is also required that you change user to the domain owner before using
+// these utilities.
+
+mystring user_dir;
+
+bool setup_user_dir()
+{
+  if(!is_exist(user_dir.c_str())) {
+    if(mkdir(user_dir.c_str(), 0755)) {
+      if(!o_quiet)
+	ferr << "vsetup: error: could not create users directory.\n";
+      return false;
+    }
+    else
+      if(!o_quiet)
+	fout << "vsetup: created users directory.\n";
+  }
+  else
+    if(!o_quiet)
+      fout << "vsetup: users directory already exists.\n";
+  return true;
+}
+
+bool setup_qmail_default()
+{
+  if(is_exist(".qmail-default")) {
+    if(!o_quiet)
+      ferr << "vsetup: warning: '.qmail-default' file exists, renaming to "
+	"'.qmail-default~'.\n";
+    if(rename(".qmail-default", ".qmail-default~")) {
+      if(!o_quiet)
+	ferr << "vsetup: error: rename failed.\n";
+      return false;
+    }
+  }
+  fdobuf out(".qmail-default", fdobuf::create | fdobuf::excl, 0644);
+  if(!out) {
+    if(!o_quiet)
+      ferr << "vsetup: error: unable to open file '.qmail-default' for output.\n";
+    return false;
+  }
+  out << "|" BINDIR "/vdeliver\n";
+  if(!out.flush() || !out.close()) {
+    if(!o_quiet)
+      ferr << "vsetup: error: writing to file '.qmail-default' failed.\n";
+    return false;
+  }
+  if(!o_quiet)
+    fout << "vsetup: wrote '.qmail-default' file.\n";
+  return true;
+}
+
+bool setup_alias(mystring alias, const mystring& dest)
+{
+  alias = alias.lower();
+  if(domain.exists(alias)) {
+    if(!o_quiet)
+      ferr << "vsetup: warning: user '" << alias
+	   << "' already exists, skipping.\n";
+    return true;
+  }
+  vpwentry vpw(alias, "*", 0, dest);
+  vpw.set_defaults(true, true);
+  response resp = domain.set(&vpw, true);
+  if(!resp) {
+    if(!o_quiet)
+      ferr << "vsetup: error: adding alias '" << alias << "' failed:\n  "
+	   << resp.msg << endl;
+    return false;
+  }
+  if(!o_quiet)
+    fout << "vsetup: added alias '" << alias << "'\n";
+  return true;
+}
+
+bool setup_passwd()
+{
+  mystring email = config->postmaster_email();
+  mystring_iter iter(config->postmaster_aliases().str());
+  while(iter) {
+    if(!setup_alias(*iter, email))
+      break;
+    ++iter;
+  }
+  return !iter;
+}
+
+int cli_main(int, char* [])
+{
+  if(!go_home())
+    return 1;
+
+  user_dir = config->user_dir();
+  
+  if(execute("vsetup-pre")) {
+    if(!o_quiet)
+      ferr << "vsetup: Execution of 'vsetup-pre' failed!\n";
+    return 1;
+  }
+  if(!setup_user_dir())
+    return 1;
+  if(!setup_qmail_default())
+    return 1;
+  if(!setup_passwd())
+    return 1;
+  if(execute("vsetup-post")) {
+    if(!o_quiet)
+      ferr << "vsetup: Execution of 'vsetup-post' failed!\n";
+    return 1;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vsetup.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,84 @@
+<HTML>
+<HEAD>
+<TITLE>vsetup - Sets up a virtual domain for its first use</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#RETURN_VALUE">RETURN VALUE</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#NOTES">NOTES</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vsetup - Sets up a virtual domain for its first use
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vsetup</STRONG>
+[<STRONG>--quiet</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program sets up the basic set of necessary files needed to use an
+account as a virtual domain with vmailmgr. The users directory is created
+if it does not exist. A <EM>.qmail-default</EM> file is created with the proper contents. If a <EM>.qmail-default</EM> previously existed, it is renamed to
+<EM>.qmail-default~</EM>. Three system aliases (<CODE>root</CODE>, <CODE>mailer-daemon</CODE>, and <CODE>postmaster</CODE>) are created to point to the configured postmaster.
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__quiet">--quiet</A></STRONG><DD>
+<P>
+Suppress all status messages.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="RETURN_VALUE">RETURN VALUE</A></H1>
+<P>
+0 if all files and directories are successfully created, 1 otherwise.
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vdeliver(1),</CODE> <CODE>vmailmgrd(8)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="NOTES">NOTES</A></H1>
+<P>
+This program expects the environment variable <CODE>HOME</CODE> to be set, and executes a change directory to the contents of it before
+starting. It is also required that you change user to the domain owner
+before using these utilities.
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/vsetup.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,60 @@
+=head1 NAME
+
+vsetup - Sets up a virtual domain for its first use
+
+=head1 SYNOPSIS
+
+B<vsetup>
+[B<--quiet>]
+
+
+=head1 DESCRIPTION
+
+This program sets up the basic set of necessary files needed to use an
+account as a virtual domain with vmailmgr.
+The users directory is created if it does not exist.
+A F<.qmail-default> file is created with the proper contents.
+If a F<.qmail-default> previously existed, it is renamed to
+F<.qmail-default~>.
+Three system aliases (C<root>, C<mailer-daemon>, and C<postmaster>)
+are created to point to the configured postmaster.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--quiet>
+
+Suppress all status messages.
+
+=back
+
+=head1 RETURN VALUE
+
+
+0 if all files and directories are successfully created, 1 otherwise.
+
+
+
+=head1 SEE ALSO
+
+
+vdeliver(1), vmailmgrd(8)
+
+
+
+=head1 NOTES
+
+
+This program expects the environment variable C<HOME> to be set, and
+executes a change directory to the contents of it before starting.  It
+is also required that you change user to the domain owner before using
+these utilities.
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,113 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef gid_t
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+#undef HAVE_SYS_WAIT_H
+
+/* Define as __inline if that's what the C compiler calls it.  */
+#undef inline
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef pid_t
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef uid_t
+
+/* Use only crypt(3) for password encryption */
+#undef USE_CRYPT
+
+/* Use Kerberos 5 authentication */
+#undef USE_KRB5
+
+#undef VPWTABLE_CDB
+#undef VPWTABLE_GDBM
+
+/* Define if you have the crypt function.  */
+#undef HAVE_CRYPT
+
+/* Define if you have the gethostname function.  */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the gettimeofday function.  */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the mkdir function.  */
+#undef HAVE_MKDIR
+
+/* Define if you have the putenv function.  */
+#undef HAVE_PUTENV
+
+/* Define if you have the random function.  */
+#undef HAVE_RANDOM
+
+/* Define if you have the rmdir function.  */
+#undef HAVE_RMDIR
+
+/* Define if you have the socket function.  */
+#undef HAVE_SOCKET
+
+/* Define if you have the srandom function.  */
+#undef HAVE_SRANDOM
+
+/* Define if you have the <crypt.h> header file.  */
+#undef HAVE_CRYPT_H
+
+/* Define if you have the <dirent.h> header file.  */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <shadow.h> header file.  */
+#undef HAVE_SHADOW_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the crypt library (-lcrypt).  */
+#undef HAVE_LIBCRYPT
+
+/* Define if you have the inet library (-linet).  */
+#undef HAVE_LIBINET
+
+/* Define if you have the socket library (-lsocket).  */
+#undef HAVE_LIBSOCKET
+
+/* Define if you have the xnet library (-lxnet).  */
+#undef HAVE_LIBXNET
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configure	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,3122 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --enable-crypt          Use only crypt(3) for authentication instead
+                           of the built-in MD5 password hashing."
+ac_help="$ac_help
+  --with-krb5             Use Kerberos5 for authentication."
+ac_help="$ac_help
+  --with-vpwtable=type    Use "type" database for storage of virtual
+                           password tables.  Defaults to "cdb"."
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=lib/mergelib.sh
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='	'
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:564: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS= 	}"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+	  if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  else
+	    ac_cv_path_install="$ac_dir/$ac_prog -c"
+	    break 2
+	  fi
+	fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:617: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "$*" != "X $srcdir/configure conftestfile" \
+      && test "$*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { echo "configure: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+   fi
+
+   test "$2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+  program_transform_name=
+else
+  # Double any \ or $.  echo might interpret backslashes.
+  cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+  program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+  rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+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:674: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+	@echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+
+PACKAGE=vmailmgr
+
+VERSION=0.96.9
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:721: checking for working aclocal" >&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
+   echo "$ac_t""found" 1>&6
+else
+   ACLOCAL="$missing_dir/missing aclocal"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:734: 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.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+   AUTOCONF=autoconf
+   echo "$ac_t""found" 1>&6
+else
+   AUTOCONF="$missing_dir/missing autoconf"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:747: checking for working automake" >&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
+   echo "$ac_t""found" 1>&6
+else
+   AUTOMAKE="$missing_dir/missing automake"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:760: 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.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+   AUTOHEADER=autoheader
+   echo "$ac_t""found" 1>&6
+else
+   AUTOHEADER="$missing_dir/missing autoheader"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:773: 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.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+   MAKEINFO=makeinfo
+   echo "$ac_t""found" 1>&6
+else
+   MAKEINFO="$missing_dir/missing makeinfo"
+   echo "$ac_t""missing" 1>&6
+fi
+
+
+
+
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:790: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+	@echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+USE_CRYPT=no
+# Check whether --enable-crypt or --disable-crypt was given.
+if test "${enable_crypt+set}" = set; then
+  enableval="$enable_crypt"
+  USE_CRYPT=$enableval
+fi
+
+test "$USE_CRYPT" != no && cat >> confdefs.h <<\EOF
+#define USE_CRYPT 1
+EOF
+
+
+# Check whether --with-krb5 or --without-krb5 was given.
+if test "${with_krb5+set}" = set; then
+  withval="$with_krb5"
+  test x$withval = xyes && withval=/usr/krb5
+ LIBS="$LIBS -L$withval/lib -lkrb5 -lcom_err -lcrypto"
+ CFLAGS="$CFLAGS -I${withval}/include"
+ CXXFLAGS="$CXXFLAGS -I${withval}/include"
+ cat >> confdefs.h <<\EOF
+#define USE_KRB5 1
+EOF
+
+fi
+
+
+
+if test x$with_krb5 != x -a x$with_krb5 != xno; then
+  KRB5_TRUE=
+  KRB5_FALSE='#'
+else
+  KRB5_TRUE='#'
+  KRB5_FALSE=
+fi
+
+# Check whether --with-vpwtable or --without-vpwtable was given.
+if test "${with_vpwtable+set}" = set; then
+  withval="$with_vpwtable"
+  case "${withval}" in
+ gdbm)	cat >> confdefs.h <<\EOF
+#define VPWTABLE_GDBM 1
+EOF
+
+	dbtype=gdbm
+	LIBS="$LIBS -lgdbm";;
+ *)    { echo "configure: error: bad value ${withval} for --with-vpwtable" 1>&2; exit 1; };;
+ esac
+else
+  cat >> confdefs.h <<\EOF
+#define VPWTABLE_CDB 1
+EOF
+
+	CDBPROGS="vpasswd2cdb vrehash"
+	CDBSCRIPTS="allvpasswd2cdb"
+	dbtype=cdb
+fi
+
+
+
+
+
+
+if test $dbtype = cdb; then
+  VPWTABLE_CDB_TRUE=
+  VPWTABLE_CDB_FALSE='#'
+else
+  VPWTABLE_CDB_TRUE='#'
+  VPWTABLE_CDB_FALSE=
+fi
+
+
+if test $dbtype = gdbm; then
+  VPWTABLE_GDBM_TRUE=
+  VPWTABLE_GDBM_FALSE='#'
+else
+  VPWTABLE_GDBM_TRUE='#'
+  VPWTABLE_GDBM_FALSE=
+fi
+
+
+
+if false; then
+  FDBUF_NO_MYSTRING_TRUE=
+  FDBUF_NO_MYSTRING_FALSE='#'
+else
+  FDBUF_NO_MYSTRING_TRUE='#'
+  FDBUF_NO_MYSTRING_FALSE=
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:909: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:939: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+	continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:990: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1022: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1033 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1038: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1064: 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:1069: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1078: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1097: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1133: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CXX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+  echo "$ac_t""$CXX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1165: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1176 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:1181: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cxx_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cxx_cross=no
+  else
+    ac_cv_prog_cxx_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+  { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1207: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:1212: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.C <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1221: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gxx=yes
+else
+  ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:1240: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+  ac_cv_prog_cxx_g=yes
+else
+  ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+
+echo $ac_n "checking whether ${CXX-g++} accepts -fno-rtti""... $ac_c" 1>&6
+echo "configure:1272: checking whether ${CXX-g++} accepts -fno-rtti" >&5
+if eval "test \"`echo '$''{'local_cv_flag_NO_RTTI'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo >conftest.cc
+if ${CXX-g++} ${CXXFLAGS} -c -fno-rtti conftest.cc >/dev/null 2>&1; then
+  rm -f conftest*
+  local_cv_flag_NO_RTTI=yes
+else
+  rm -f conftest*
+  local_cv_flag_NO_RTTI=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$local_cv_flag_NO_RTTI" 1>&6
+test "$local_cv_flag_NO_RTTI" = yes && CXXFLAGS="$CXXFLAGS -fno-rtti"
+
+echo $ac_n "checking whether ${CXX-g++} accepts -fno-exceptions""... $ac_c" 1>&6
+echo "configure:1291: checking whether ${CXX-g++} accepts -fno-exceptions" >&5
+if eval "test \"`echo '$''{'local_cv_flag_NO_EXCEPTIONS'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo >conftest.cc
+if ${CXX-g++} ${CXXFLAGS} -c -fno-exceptions conftest.cc >/dev/null 2>&1; then
+  rm -f conftest*
+  local_cv_flag_NO_EXCEPTIONS=yes
+else
+  rm -f conftest*
+  local_cv_flag_NO_EXCEPTIONS=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$local_cv_flag_NO_EXCEPTIONS" 1>&6
+test "$local_cv_flag_NO_EXCEPTIONS" = yes && CXXFLAGS="$CXXFLAGS -fno-exceptions"
+
+
+CFLAGS="$CFLAGS -Wall -W"
+CXXFLAGS="$CXXFLAGS -Wall -W"
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1325: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS= 	}"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+	  if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  else
+	    ac_cv_path_install="$ac_dir/$ac_prog -c"
+	    break 2
+	  fi
+	fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1380: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1410: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_STRIP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$STRIP" in
+  /*)
+  ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path.
+  ;;
+  ?:/*)			 
+  ac_cv_path_STRIP="$STRIP" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_STRIP="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+fi
+STRIP="$ac_cv_path_STRIP"
+if test -n "$STRIP"; then
+  echo "$ac_t""$STRIP" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1445: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$RM" in
+  /*)
+  ac_cv_path_RM="$RM" # Let the user override the test with a path.
+  ;;
+  ?:/*)			 
+  ac_cv_path_RM="$RM" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_RM="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+fi
+RM="$ac_cv_path_RM"
+if test -n "$RM"; then
+  echo "$ac_t""$RM" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "mkdir", so it can be a program name with args.
+set dummy mkdir; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1480: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$MKDIR" in
+  /*)
+  ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path.
+  ;;
+  ?:/*)			 
+  ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_MKDIR="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+fi
+MKDIR="$ac_cv_path_MKDIR"
+if test -n "$MKDIR"; then
+  echo "$ac_t""$MKDIR" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "ln", so it can be a program name with args.
+set dummy ln; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1515: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_LN'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$LN" in
+  /*)
+  ac_cv_path_LN="$LN" # Let the user override the test with a path.
+  ;;
+  ?:/*)			 
+  ac_cv_path_LN="$LN" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_LN="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+fi
+LN="$ac_cv_path_LN"
+if test -n "$LN"; then
+  echo "$ac_t""$LN" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+# Extract the first word of "python", so it can be a program name with args.
+set dummy python; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1551: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_PYTHON'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$PYTHON" in
+  /*)
+  ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+  ;;
+  ?:/*)			 
+  ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_PYTHON="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+fi
+PYTHON="$ac_cv_path_PYTHON"
+if test -n "$PYTHON"; then
+  echo "$ac_t""$PYTHON" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking Python library path""... $ac_c" 1>&6
+echo "configure:1584: checking Python library path" >&5
+if eval "test \"`echo '$''{'local_cv_python_lib_dir'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -x "$PYTHON"; then
+  local_cv_python_lib_dir=`$PYTHON -c "import sys;print sys.path[1]"`
+else
+  local_cv_python_lib_dir=NONE
+fi
+fi
+
+echo "$ac_t""$local_cv_python_lib_dir" 1>&6
+pythonlibdir="$local_cv_python_lib_dir/vmailmgr"
+
+
+
+if test x$local_cv_python_lib_dir != xNONE; then
+  WANTPYTHON_TRUE=
+  WANTPYTHON_FALSE='#'
+else
+  WANTPYTHON_TRUE='#'
+  WANTPYTHON_FALSE=
+fi
+
+phpdir="/home/httpd/php"
+
+
+# Extract the first word of "w3m", so it can be a program name with args.
+set dummy w3m; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1614: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_W3M'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$W3M" in
+  /*)
+  ac_cv_path_W3M="$W3M" # Let the user override the test with a path.
+  ;;
+  ?:/*)			 
+  ac_cv_path_W3M="$W3M" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_W3M="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+fi
+W3M="$ac_cv_path_W3M"
+if test -n "$W3M"; then
+  echo "$ac_t""$W3M" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "lynx", so it can be a program name with args.
+set dummy lynx; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1649: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_LYNX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$LYNX" in
+  /*)
+  ac_cv_path_LYNX="$LYNX" # Let the user override the test with a path.
+  ;;
+  ?:/*)			 
+  ac_cv_path_LYNX="$LYNX" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_LYNX="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+fi
+LYNX="$ac_cv_path_LYNX"
+if test -n "$LYNX"; then
+  echo "$ac_t""$LYNX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test "x$W3M" != x; then
+  echo Using w3m to format html pages.
+  HTML2TXT="w3m -dump"
+elif test "x$LYNX" != x; then
+  echo Using lynx to format html pages.
+  HTML2TXT="lynx -dump -nolist"
+else
+  echo "Can't find either w3m or lynx, building the plain text"
+  echo "documentation files will fail."
+  HTML2TXT="false"
+fi
+
+
+TODAY=`date +%Y-%m-%d`
+POD2MAN="pod2man --release='vmailmgr ${VERSION}' --center='VMailMgr Tools Documentation' --date='${TODAY}'"
+POD2HTML="pod2html --noindex"
+SUFFIXES="$SUFFIXES .1 .5 .7 .8 .pod .html .texi .txt .ps .fig .sgml .py .pyc .pyo"
+
+
+
+
+echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
+echo "configure:1703: checking for crypt in -lcrypt" >&5
+ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lcrypt  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1711 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char crypt();
+
+int main() {
+crypt()
+; return 0; }
+EOF
+if { (eval echo configure:1722: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo crypt | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lcrypt $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
+echo "configure:1750: checking for socket in -linet" >&5
+ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-linet  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1758 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1769: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo inet | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-linet $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:1797: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lsocket  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1805 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1816: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lsocket $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for socket in -lxnet""... $ac_c" 1>&6
+echo "configure:1844: checking for socket in -lxnet" >&5
+ac_lib_var=`echo xnet'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lxnet  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1852 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1863: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo xnet | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lxnet $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:1896: 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 1901 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:1909: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:1934: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldir  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1942 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1953: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBS="$LIBS -ldir"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:1975: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lx  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1983 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1994: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBS="$LIBS -lx"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:2017: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 2032 "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:2038: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 2049 "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:2055: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 2066 "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:2072: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2097: 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 2102 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2110: \"$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*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+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 2127 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+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 2145 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2166 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2177: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:2201: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2206 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:2222: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:2243: 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 2248 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:2257: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_header_time=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+  cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+for ac_hdr in fcntl.h sys/time.h unistd.h shadow.h crypt.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2281: 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 2286 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2291: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2319: 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 2324 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this.  */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this.  */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this.  */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+   It does not let you subtract one const X* pointer from another in an arm
+   of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this.  */
+  char *t;
+  char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+  *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+  int x[] = {25, 17};
+  const int *foo = &x[0];
+  ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+  typedef const int *iptr;
+  iptr p = 0;
+  ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+     "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+  struct s { int j; const int *ap[3]; };
+  struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+  const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2373: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_const=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+  cat >> confdefs.h <<\EOF
+#define const 
+EOF
+
+fi
+
+echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:2394: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2399 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "uid_t" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_uid_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
+  cat >> confdefs.h <<\EOF
+#define uid_t int
+EOF
+
+  cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+
+fi
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:2428: 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 2433 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:2450: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_type_signal=void
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:2469: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat > conftest.$ac_ext <<EOF
+#line 2476 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:2483: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_inline=$ac_kw; break
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+  inline | yes) ;;
+  no) cat >> confdefs.h <<\EOF
+#define inline 
+EOF
+ ;;
+  *)  cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:2509: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2514 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_pid_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+  cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:2542: 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 2547 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_size_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+  cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+
+for ac_func in gethostname gettimeofday mkdir putenv rmdir socket
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2578: 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 2583 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2606: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in srandom random crypt
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2633: 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 2638 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+cgidir='${prefix}/cgi-bin'
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[ 	]*VPATH[ 	]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile
+          cgi/Makefile
+	  authenticate/Makefile
+	  commands/Makefile
+	  daemon/Makefile
+	  doc/Makefile
+          lib/Makefile
+	  lib/cdb++/Makefile
+	  lib/cgi/Makefile
+	  lib/cli/Makefile
+	  lib/config/Makefile
+	  lib/courier-authlib/Makefile
+	  lib/fdbuf/Makefile
+	  lib/misc/Makefile
+	  lib/mystring/Makefile
+	  lib/vdomain/Makefile
+	  lib/vpwentry/Makefile
+	  lib/vpwtable/Makefile
+	  scripts/Makefile
+	  php/Makefile
+	  python/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@KRB5_TRUE@%$KRB5_TRUE%g
+s%@KRB5_FALSE@%$KRB5_FALSE%g
+s%@CDBPROGS@%$CDBPROGS%g
+s%@CDBSCRIPTS@%$CDBSCRIPTS%g
+s%@VPWTABLE_CDB_TRUE@%$VPWTABLE_CDB_TRUE%g
+s%@VPWTABLE_CDB_FALSE@%$VPWTABLE_CDB_FALSE%g
+s%@VPWTABLE_GDBM_TRUE@%$VPWTABLE_GDBM_TRUE%g
+s%@VPWTABLE_GDBM_FALSE@%$VPWTABLE_GDBM_FALSE%g
+s%@FDBUF_NO_MYSTRING_TRUE@%$FDBUF_NO_MYSTRING_TRUE%g
+s%@FDBUF_NO_MYSTRING_FALSE@%$FDBUF_NO_MYSTRING_FALSE%g
+s%@CC@%$CC%g
+s%@CXX@%$CXX%g
+s%@RANLIB@%$RANLIB%g
+s%@STRIP@%$STRIP%g
+s%@RM@%$RM%g
+s%@MKDIR@%$MKDIR%g
+s%@LN@%$LN%g
+s%@PYTHON@%$PYTHON%g
+s%@pythonlibdir@%$pythonlibdir%g
+s%@WANTPYTHON_TRUE@%$WANTPYTHON_TRUE%g
+s%@WANTPYTHON_FALSE@%$WANTPYTHON_FALSE%g
+s%@phpdir@%$phpdir%g
+s%@W3M@%$W3M%g
+s%@LYNX@%$LYNX%g
+s%@HTML2TXT@%$HTML2TXT%g
+s%@POD2MAN@%$POD2MAN%g
+s%@POD2HTML@%$POD2HTML%g
+s%@SUFFIXES@%$SUFFIXES%g
+s%@CPP@%$CPP%g
+s%@cgidir@%$cgidir%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile
+          cgi/Makefile
+	  authenticate/Makefile
+	  commands/Makefile
+	  daemon/Makefile
+	  doc/Makefile
+          lib/Makefile
+	  lib/cdb++/Makefile
+	  lib/cgi/Makefile
+	  lib/cli/Makefile
+	  lib/config/Makefile
+	  lib/courier-authlib/Makefile
+	  lib/fdbuf/Makefile
+	  lib/misc/Makefile
+	  lib/mystring/Makefile
+	  lib/vdomain/Makefile
+	  lib/vpwentry/Makefile
+	  lib/vpwtable/Makefile
+	  scripts/Makefile
+	  php/Makefile
+	  python/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
+ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_uB='\([ 	]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configure.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,143 @@
+AC_INIT(lib/mergelib.sh)
+AM_INIT_AUTOMAKE(vmailmgr, 0.96.9)
+AM_CONFIG_HEADER(config.h)
+AC_PROG_MAKE_SET
+
+USE_CRYPT=no
+AC_ARG_ENABLE(crypt,
+[  --enable-crypt          Use only crypt(3) for authentication instead
+                           of the built-in MD5 password hashing.],
+USE_CRYPT=$enableval)
+test "$USE_CRYPT" != no && AC_DEFINE(USE_CRYPT)
+
+AC_ARG_WITH(krb5,
+[  --with-krb5             Use Kerberos5 for authentication.],
+[test x$withval = xyes && withval=/usr/krb5
+ LIBS="$LIBS -L$withval/lib -lkrb5 -lcom_err -lcrypto"
+ CFLAGS="$CFLAGS -I${withval}/include"
+ CXXFLAGS="$CXXFLAGS -I${withval}/include"
+ AC_DEFINE(USE_KRB5)])
+AM_CONDITIONAL(KRB5, test x$with_krb5 != x -a x$with_krb5 != xno)
+
+AC_ARG_WITH(vpwtable,
+[  --with-vpwtable=type    Use "type" database for storage of virtual
+                           password tables.  Defaults to "cdb".],
+[case "${withval}" in
+ gdbm)	AC_DEFINE(VPWTABLE_GDBM)
+	dbtype=gdbm
+	LIBS="$LIBS -lgdbm";;
+ *)    AC_MSG_ERROR(bad value ${withval} for --with-vpwtable);;
+ esac],[AC_DEFINE(VPWTABLE_CDB)
+	CDBPROGS="vpasswd2cdb vrehash"
+	CDBSCRIPTS="allvpasswd2cdb"
+	dbtype=cdb])
+
+AC_SUBST(CDBPROGS)
+AC_SUBST(CDBSCRIPTS)
+AM_CONDITIONAL(VPWTABLE_CDB, test $dbtype = cdb)
+AM_CONDITIONAL(VPWTABLE_GDBM, test $dbtype = gdbm)
+
+AM_CONDITIONAL(FDBUF_NO_MYSTRING, false)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+CXX_NO_RTTI
+CXX_NO_EXCEPTIONS
+
+CFLAGS="$CFLAGS -Wall -W"
+CXXFLAGS="$CXXFLAGS -Wall -W"
+
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+AC_PATH_PROG(STRIP, strip)
+AC_PATH_PROG(RM, rm)
+AC_PATH_PROG(MKDIR, mkdir)
+AC_PATH_PROG(LN, ln)
+
+AC_PATH_PROG(PYTHON, python)
+AC_CACHE_CHECK(Python library path, local_cv_python_lib_dir,
+[[if test -x "$PYTHON"; then
+  local_cv_python_lib_dir=`$PYTHON -c "import sys;print sys.path[1]"`
+else
+  local_cv_python_lib_dir=NONE
+fi]])
+pythonlibdir="$local_cv_python_lib_dir/vmailmgr"
+AC_SUBST(pythonlibdir)
+AM_CONDITIONAL(WANTPYTHON, test x$local_cv_python_lib_dir != xNONE)
+
+phpdir="/home/httpd/php"
+AC_SUBST(phpdir)
+
+AC_PATH_PROG(W3M, w3m)
+AC_PATH_PROG(LYNX, lynx)
+if test "x$W3M" != x; then
+  echo Using w3m to format html pages.
+  HTML2TXT="w3m -dump"
+elif test "x$LYNX" != x; then
+  echo Using lynx to format html pages.
+  HTML2TXT="lynx -dump -nolist"
+else
+  echo "Can't find either w3m or lynx, building the plain text"
+  echo "documentation files will fail."
+  HTML2TXT="false"
+fi
+AC_SUBST(HTML2TXT)
+
+TODAY=`date +%Y-%m-%d`
+POD2MAN="pod2man --release='vmailmgr ${VERSION}' --center='VMailMgr Tools Documentation' --date='${TODAY}'"
+POD2HTML="pod2html --noindex"
+SUFFIXES="$SUFFIXES .1 .5 .7 .8 .pod .html .texi .txt .ps .fig .sgml .py .pyc .pyo"
+AC_SUBST(POD2MAN)
+AC_SUBST(POD2HTML)
+AC_SUBST(SUFFIXES)
+
+dnl Checks for libraries.
+AC_CHECK_LIB(crypt, crypt)
+AC_CHECK_LIB(inet, socket)
+AC_CHECK_LIB(socket, socket)
+AC_CHECK_LIB(xnet, socket)
+
+dnl Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_HEADER_TIME
+AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h shadow.h crypt.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_UID_T
+AC_TYPE_SIGNAL
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(gethostname gettimeofday mkdir putenv rmdir socket)
+AC_CHECK_FUNCS(srandom random crypt)
+
+cgidir='${prefix}/cgi-bin'
+AC_SUBST(cgidir)
+
+AC_OUTPUT(Makefile
+          cgi/Makefile
+	  authenticate/Makefile
+	  commands/Makefile
+	  daemon/Makefile
+	  doc/Makefile
+          lib/Makefile
+	  lib/cdb++/Makefile
+	  lib/cgi/Makefile
+	  lib/cli/Makefile
+	  lib/config/Makefile
+	  lib/courier-authlib/Makefile
+	  lib/fdbuf/Makefile
+	  lib/misc/Makefile
+	  lib/mystring/Makefile
+	  lib/vdomain/Makefile
+	  lib/vpwentry/Makefile
+	  lib/vpwtable/Makefile
+	  scripts/Makefile
+	  php/Makefile
+	  python/Makefile)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,39 @@
+sbin_PROGRAMS = vmailmgrd
+
+noinst_PODS = vmailmgrd.pod
+noinst_HTMLS = $(noinst_PODS:.pod=.html)
+man_MANS = $(noinst_PODS:.pod=.8)
+
+CLEANFILES = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS) \
+	pod2html-dircache pod2html-itemcache
+EXTRA_DIST = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS)
+
+all: docs
+
+docs: $(noinst_HTMLS) $(noinst_TXTS)
+
+dist-hook:
+	touch $(distdir)/*.html $(distdir)/*.[123456789]
+
+vmailmgrd.pod: main.cc ../configure.in ../lib/cli/cli2pod.pl
+	perl ../lib/cli/cli2pod.pl $< >$@
+%.8: %.pod ../configure.in; $(POD2MAN) --section=8 $< >$@
+%.html: %.pod; $(POD2HTML) $< >$@
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = -I../lib
+
+vmailmgrd_SOURCES = daemon.h \
+	adduser2.cc \
+	autoresponse.cc \
+	chattr.cc \
+	check.cc \
+	command.h command.cc \
+	deluser.cc \
+	dispatch.cc \
+	listdomain.cc \
+	log.h log.cc \
+	lookup.cc \
+	main.cc \
+	state.h state.cc
+vmailmgrd_LDADD = ../lib/libvmailmgr.a ../lib/cli/libcli.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,506 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+sbin_PROGRAMS = vmailmgrd
+
+noinst_PODS = vmailmgrd.pod
+noinst_HTMLS = $(noinst_PODS:.pod=.html)
+man_MANS = $(noinst_PODS:.pod=.8)
+
+CLEANFILES = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS) 	pod2html-dircache pod2html-itemcache
+
+EXTRA_DIST = $(man_MANS) $(noinst_HTMLS) $(noinst_PODS)
+
+CXXLINK = $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@
+INCLUDES = -I../lib
+
+vmailmgrd_SOURCES = daemon.h 	adduser2.cc 	autoresponse.cc 	chattr.cc 	check.cc 	command.h command.cc 	deluser.cc 	dispatch.cc 	listdomain.cc 	log.h log.cc 	lookup.cc 	main.cc 	state.h state.cc
+
+vmailmgrd_LDADD = ../lib/libvmailmgr.a ../lib/cli/libcli.a
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(sbin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+vmailmgrd_OBJECTS =  adduser2.o autoresponse.o chattr.o check.o \
+command.o deluser.o dispatch.o listdomain.o log.o lookup.o main.o \
+state.o
+vmailmgrd_DEPENDENCIES =  ../lib/libvmailmgr.a ../lib/cli/libcli.a
+vmailmgrd_LDFLAGS = 
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man8dir = $(mandir)/man8
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(vmailmgrd_SOURCES)
+OBJECTS = $(vmailmgrd_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps daemon/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-sbinPROGRAMS:
+
+clean-sbinPROGRAMS:
+	-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+
+distclean-sbinPROGRAMS:
+
+maintainer-clean-sbinPROGRAMS:
+
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sbindir)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "  $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	     $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+vmailmgrd: $(vmailmgrd_OBJECTS) $(vmailmgrd_DEPENDENCIES)
+	@rm -f vmailmgrd
+	$(CXXLINK) $(vmailmgrd_LDFLAGS) $(vmailmgrd_OBJECTS) $(vmailmgrd_LDADD) $(LIBS)
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+install-man8:
+	$(mkinstalldirs) $(DESTDIR)$(man8dir)
+	@list='$(man8_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \
+	  $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \
+	done
+
+uninstall-man8:
+	@list='$(man8_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \
+	  rm -f $(DESTDIR)$(man8dir)/$$inst; \
+	done
+install-man: $(MANS)
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-man8
+uninstall-man:
+	@$(NORMAL_UNINSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-man8
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = daemon
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+addalias.o: addalias.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/fdbuf/fdbuf.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpw/vpwentry.h ../lib/misc/pwcrypt.h ../lib/misc/itoa.h \
+	state.h ../lib/misc/vdomain.h ../lib/vpw/vpwtable.h \
+	../lib/misc/response.h command.h log.h
+addaliasp.o: addaliasp.cc ../config.h daemon.h \
+	../lib/mystring/mystring.h ../lib/fdbuf/fdbuf.h \
+	../lib/misc/pwentry.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vpw/vpwentry.h \
+	../lib/misc/pwcrypt.h ../lib/misc/itoa.h state.h \
+	../lib/misc/vdomain.h ../lib/vpw/vpwtable.h \
+	../lib/misc/response.h command.h log.h
+adduser.o: adduser.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/fdbuf/fdbuf.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpw/vpwentry.h ../lib/misc/pwcrypt.h ../lib/misc/itoa.h \
+	state.h ../lib/misc/vdomain.h ../lib/vpw/vpwtable.h \
+	../lib/misc/response.h command.h log.h
+adduser2.o: adduser2.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+autoresponse.o: autoresponse.cc ../config.h daemon.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/pwentry.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/pwcrypt.h ../lib/misc/itoa.h state.h \
+	../lib/vdomain/vdomain.h ../lib/vpwtable/vpwtable.h \
+	../lib/misc/response.h command.h log.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/misc/lookup.h ../lib/misc/maildir.h \
+	../lib/misc/pwentry_table.h ../lib/misc/stat_fns.h
+chattr.o: chattr.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+check.o: check.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+command.o: command.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+deluser.o: deluser.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+dispatch.o: dispatch.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h ../lib/misc/lookup.h
+fork.o: fork.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h ../lib/ac/wait.h
+listdomain.o: listdomain.cc ../config.h daemon.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/pwentry.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/pwcrypt.h ../lib/misc/itoa.h state.h \
+	../lib/vdomain/vdomain.h ../lib/vpwtable/vpwtable.h \
+	../lib/misc/response.h command.h log.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h \
+	../lib/misc/lookup.h
+log.o: log.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h
+lookup.o: lookup.cc ../config.h daemon.h ../lib/mystring/mystring.h \
+	../lib/mystring/rep.h ../lib/mystring/iter.h \
+	../lib/mystring/join.h ../lib/misc/pwentry.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/pwcrypt.h \
+	../lib/misc/itoa.h state.h ../lib/vdomain/vdomain.h \
+	../lib/vpwtable/vpwtable.h ../lib/misc/response.h command.h \
+	log.h ../lib/fdbuf/fdbuf.h ../lib/fdbuf/fdibuf.h \
+	../lib/fdbuf/fdobuf.h ../lib/misc/lookup.h \
+	../lib/misc/pwentry_table.h
+main.o: main.cc ../config.h ../lib/cli/cli.h daemon.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/misc/pwentry.h ../lib/config/configrc.h \
+	../lib/misc/strlist.h ../lib/vpwentry/vpwentry.h \
+	../lib/misc/pwcrypt.h ../lib/misc/itoa.h state.h \
+	../lib/vdomain/vdomain.h ../lib/vpwtable/vpwtable.h \
+	../lib/misc/response.h command.h log.h ../lib/fdbuf/fdbuf.h \
+	../lib/fdbuf/fdibuf.h ../lib/fdbuf/fdobuf.h
+state.o: state.cc state.h ../lib/misc/pwentry.h \
+	../lib/mystring/mystring.h ../lib/mystring/rep.h \
+	../lib/mystring/iter.h ../lib/mystring/join.h \
+	../lib/config/configrc.h ../lib/misc/strlist.h \
+	../lib/vdomain/vdomain.h ../lib/vpwtable/vpwtable.h \
+	../lib/vpwentry/vpwentry.h ../lib/misc/response.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-sbinPROGRAMS
+install-exec: install-exec-am
+
+install-data-am: install-man
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-sbinPROGRAMS uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8
+
+
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-sbinPROGRAMS mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-sbinPROGRAMS clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-sbinPROGRAMS distclean-compile distclean-tags \
+		distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-sbinPROGRAMS \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS \
+clean-sbinPROGRAMS maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \
+install-sbinPROGRAMS mostlyclean-compile distclean-compile \
+clean-compile maintainer-clean-compile install-man8 uninstall-man8 \
+install-man uninstall-man tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+all: docs
+
+docs: $(noinst_HTMLS) $(noinst_TXTS)
+
+dist-hook:
+	touch $(distdir)/*.html $(distdir)/*.[123456789]
+
+vmailmgrd.pod: main.cc ../configure.in ../lib/cli/cli2pod.pl
+	perl ../lib/cli/cli2pod.pl $< >$@
+%.8: %.pod ../configure.in; $(POD2MAN) --section=8 $< >$@
+%.html: %.pod; $(POD2HTML) $< >$@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/adduser2.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,63 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include "daemon.h"
+
+response build_forwards(const command& args, int offset,
+			vpwentry* vpw, vdomain& domain)
+{
+  bool first = true;
+  for(unsigned i = offset; i < args.count(); i++) {
+    if(!!args[i]) {
+      OK_RESPONSE(domain.validate_forward(args[i]));
+      if(!first)
+	vpw->forwards = vpw->forwards + mystring::NUL + args[i];
+      else {
+	vpw->forwards = args[i];
+	first = false;
+      }
+    }
+  }
+  RETURN(ok, "");
+}
+
+CMD(adduser2)
+  // Usage: adduser2 baseuser-virtuser adminpass newpass dirname [forwards ...]
+  // If <newpass> is empty, a null-password is used.
+  // If <dirname> is empty, no user directory is created.
+  // <dirname> should normally be the same as virtuser.
+{
+  mystring fulluser = args[0];
+  mystring adminpass = args[1];
+  mystring newpass = args[2];
+  mystring dirname = args[3];
+  args[1] = LOG_ADMINPASS;
+  args[2] = LOG_NEWPASS;
+  logcommand(args);
+  
+  pwentry* pw;
+  vpwentry* vpw;
+  OK_RESPONSE(lookup_and_validate(fulluser, pw, vpw, adminpass, false));
+  OK_RESPONSE(build_forwards(args, 4, vpw, state->domain));
+  if(!!newpass)
+    vpw->pass = pwcrypt(newpass);
+  if(!!dirname)
+    vpw->mailbox = "./" + state->domain.userdir(dirname);
+  return state->domain.set(vpw, true, vpw->mailbox);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/autoresponse.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,184 @@
+// Copyright (C) 2000 Mike Bell <mike@mikebell.org>,
+// Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include "daemon.h"
+#include "config/configrc.h"
+#include "misc/response.h"
+#include "misc/lookup.h"
+#include "misc/maildir.h"
+#include "misc/pwentry_table.h"
+#include "misc/stat_fns.h"
+
+response autoresponse_write(const mystring& directory,
+			    const mystring& location,
+			    const mystring& disabled,
+			    const mystring& msg)
+{
+  mystring tmpfile = location + ".lock";
+
+  if(!is_dir(directory.c_str())) {
+    if(mkdir(directory.c_str(), 0755))
+      RETURN(err, "Could not create autoresponse directory");
+  }
+  
+  if(is_exist(tmpfile.c_str()))
+    RETURN(err, "Temporary autoresponse file already exists");
+
+  if(is_exist(disabled.c_str()))
+    RETURN(err, "Autoresponse is disabled, reenable it before writing a new message");
+  
+  fdobuf out(tmpfile.c_str(), fdobuf::create | fdobuf::excl, 0644);
+  if(!out)
+    RETURN(err, "Unable to open temporary autoresponse file for writing");
+
+  out << msg;
+  if(!out.flush() || !out.close()) {
+    unlink(tmpfile.c_str());
+    RETURN(err, "Unable to write message to file");
+  }
+  if(rename(tmpfile.c_str(), location.c_str())) {
+    unlink(tmpfile.c_str());
+    RETURN(err, "Unable to rename temporary autoresponse file");
+  }
+
+  RETURN(ok, "Message successfully written to autoresponse file");
+}
+
+response autoresponse_disable(const mystring& location,
+			      const mystring& disabled)
+{
+  if(!is_exist(location.c_str()))
+    RETURN(ok, "Autoresponse file did not exist");
+  if(is_exist(disabled.c_str()))
+    RETURN(err, "Disabled autoresponse file already exists");
+  if(rename(location.c_str(), disabled.c_str()))
+    RETURN(err, "Unable to rename autoresponse file");
+  RETURN(ok, "Autoresponse file sucessfully disabled");
+}  
+
+response autoresponse_enable(const mystring& location,
+			     const mystring& disabled)
+{
+  if(is_exist(location.c_str()))
+    RETURN(ok, "Autoresponse is already enabled");
+  if(!is_exist(disabled.c_str()))
+    RETURN(err, "Disabled autoresponse file did not exist");
+  if(rename(disabled.c_str(), location.c_str()))
+    RETURN(err, "Unable to rename previously disabled autoresponse file");
+  RETURN(ok, "Autoresponse file sucessfully restored");
+}  
+
+static bool read_file(const mystring& filename, mystring& out)
+{
+  fdibuf in(filename.c_str());
+  if(!in)
+    return false;
+  char contents[65536];
+  unsigned contentlen;
+  in.read(contents, 65536);
+  contentlen = in.last_count();
+  out = mystring(contents, contentlen);
+  return true;
+}
+
+response autoresponse_read(const mystring& location,
+			   const mystring& disabled, int fd)
+{
+  mystring line;
+  if(!is_exist(location.c_str()) &&
+     !is_exist(disabled.c_str()))
+    RETURN(err, "Autoresponder file does not exist");
+
+  mystring contents;
+  if(!read_file(location, contents) &&
+     !read_file(disabled, contents))
+    RETURN(err, "Unable to read data from autoresponse file");
+  response resp(response::ok, contents);
+  resp.write(fd);
+  RETURN(ok, "Retrieved autoresponse file");
+}
+
+response autoresponse_delete(const mystring& directory)
+{
+  if(!is_dir(directory.c_str()))
+    RETURN(err, "Autoresponse directory does not exist.");
+  if(!delete_directory(directory))
+    RETURN(err, "Could not delete autoresponse directory.");
+  RETURN(ok, "Autoresponse directory deleted.");
+}
+
+response autoresponse_status(const mystring& directory,
+			     const mystring& location,
+			     const mystring& disabled)
+{
+  const char* msg;
+  if(is_exist(location.c_str()))
+    msg = "enabled";
+  else if(is_exist(disabled.c_str()))
+    msg = "disabled";
+  else if(is_dir(directory.c_str()))
+    msg = "missing message file";
+  else
+    msg = "nonexistant";
+  RETURN(ok, msg);
+}
+
+CMD_FD(autoresponse)
+  // Usage: autoresponse baseuser-virtuser pass action [autorespmessage]
+{
+
+  mystring user = args[0];
+  mystring pass = args[1];
+  args[1] = LOG_PASSWORD;
+  mystring action = args[2];
+  mystring message;
+  if(args.count() == 4) {
+    message = args[3];
+    args[3] = LOG_MESSAGE;
+  }
+  logcommand(args);
+
+  pwentry* pw;
+  vpwentry* vpw;
+  OK_RESPONSE(lookup_and_validate(user, pw, vpw, pass, true, true));
+
+  const mystring directory = vpw->mailbox + "/" + config->autoresponse_dir();
+  const mystring filename = directory + "/" + config->autoresponse_file();
+  const mystring disabled = filename + ".disabled";
+  
+  if(action == "disable")
+    return autoresponse_disable(filename, disabled);
+  else if(action == "enable")
+    return autoresponse_enable(filename, disabled);
+  else if(action == "read")
+    return autoresponse_read(filename, disabled, fd);
+  else if(action == "write")
+    if(!message)
+      RETURN(bad, "Missing autoresponse message argument");
+    else
+      return autoresponse_write(directory, filename, disabled, message);
+  else if(action == "delete")
+    return autoresponse_delete(directory);
+  else if(action == "status")
+    return autoresponse_status(directory, filename, disabled);
+  
+  RETURN(err, "Unrecognized command");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/chattr.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,52 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include "daemon.h"
+
+CMD(chattr)
+  // Usage: chattr baseuser-virtuser pass attribute value [value ...]
+{
+  mystring user = args[0];
+  mystring pass = args[1];
+  mystring attr = args[2];
+  mystring newval = args[3];
+  for(unsigned i = 4; i < args.count(); i++)
+    if(!!args[i])
+      newval = newval + string::NUL + args[i];
+  
+  unsigned aval = strtoul(attr.c_str(), 0, 0);
+  bool userpass = false;
+  switch(aval) {
+  case vdomain::ATTR_PASS:
+    args[3] = LOG_NEWPASS;
+    userpass = true;
+    break;
+  case vdomain::ATTR_DEST:
+  case vdomain::ATTR_MAILBOX_ENABLED:
+    userpass = true;
+    break;
+  }
+  args[1] = LOG_PASSWORD;
+  logcommand(args);
+
+  pwentry* pw;
+  vpwentry* vpw;
+  OK_RESPONSE(lookup_and_validate(user, pw, vpw, pass, true, userpass));
+  return state->domain.chattr(vpw, aval, newval);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/check.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,48 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "daemon.h"
+#include "misc/itoa.h"
+
+CMD(check)
+  // Usage: check username-virtname password
+  // Result: None
+{
+  mystring fulluser = args[0];
+  mystring password = args[1];
+  args[1] = LOG_PASSWORD;
+  logcommand(args);
+
+  mystring virtname;
+  pwentry* basepw;
+  if(!lookup_baseuser(fulluser, basepw, virtname))
+    RETURN(err, "Invalid or unknown base user or domain");
+  if(!virtname) {
+    if(basepw->authenticate(password))
+      RETURN(ok, "");
+  }
+  else {
+    state = new saved_state(basepw);
+    vpwentry* virtpw = state->domain.lookup(virtname, false);
+    if(!virtpw)
+      RETURN(err, "Invalid or unknown virtual user");
+    if(virtpw->authenticate(password))
+      RETURN(ok, "");
+  }
+  RETURN(err, "Invalid or incorrect password");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/command.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,46 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "daemon.h"
+
+command::command(mystring c, unsigned a)
+  : cmd(c), argc(a), args(new mystring*[a])
+{
+  for(unsigned i = 0; i < argc; i++)
+    args[i] = new mystring;
+}
+
+command::~command()
+{
+  for(unsigned i = 0; i < argc; i++)
+    delete args[i];
+  delete[] args;
+}
+
+bool command::replace_first_two(mystring newfirst)
+{
+  if(argc < 2)
+    return false;
+  delete args[0];
+  args[0] = new mystring(newfirst);
+  delete args[1];
+  for(unsigned i = 2; i < argc; i++)
+    args[i-1] = args[i];
+  args[argc-1] = 0;
+  --argc;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/command.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,25 @@
+#ifndef VMAILMGR__DAEMON__COMMAND__H__
+#define VMAILMGR__DAEMON__COMMAND__H__
+
+#include "mystring/mystring.h"
+
+class command
+{
+private:
+  const mystring cmd;
+  unsigned argc;
+  mystring** args;
+  command();
+  command(const command&);
+public:
+  command(mystring, unsigned);
+  ~command();
+  mystring& operator[](unsigned i) { return *args[i]; }
+  mystring operator[](unsigned i) const { return *args[i]; }
+  mystring name() const { return cmd; }
+  unsigned count() const { return argc; }
+
+  bool replace_first_two(mystring);
+};
+  
+#endif // VMAILMGR__DAEMON__COMMAND__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/daemon.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,56 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef VMAILMGR__VMAILMGRD__H__
+#define VMAILMGR__VMAILMGRD__H__
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include "mystring/mystring.h"
+#include "misc/pwentry.h"
+#include "vpwentry/vpwentry.h"
+#include "misc/pwcrypt.h"
+#include "misc/itoa.h"
+#include "config/configrc.h"
+#include "state.h"
+#include "misc/response.h"
+#include "command.h"
+#include "log.h"
+#include "vdomain/vdomain.h"
+
+typedef unsigned char uchar;
+
+// from dispatch.cc
+extern response dispatch_cmd(command& args, int fd);
+
+#define CMD(NAME) response NAME##_cmd (command& args, int)
+#define CMD_FD(NAME) response NAME##_cmd (command& args, int fd)
+
+// from lookup.cc
+extern bool lookup_baseuser(mystring, pwentry*&, mystring&);
+extern response lookup_and_validate(const mystring&, pwentry*&, vpwentry*&,
+				    const mystring& password,
+				    bool mustexist = true,
+				    bool userpass = false);
+
+// from fork.cc
+extern void handle_children(int);
+extern pid_t do_fork();
+
+#define OK_RESPONSE(FN) do { response resp = (FN); if(!resp) return resp; } while(0)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/deluser.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,34 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include "daemon.h"
+
+CMD(deluser)
+  // Usage: deluser baseuser-virtuser adminpass
+{
+  mystring fulluser = args[0];
+  mystring adminpass = args[1];
+  args[1] = LOG_ADMINPASS;
+  logcommand(args);
+  
+  pwentry* pw;
+  vpwentry* vpw;
+  OK_RESPONSE(lookup_and_validate(fulluser, pw, vpw, adminpass));
+  return state->domain.deluser(vpw->name, true);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/dispatch.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,147 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "daemon.h"
+#include "misc/lookup.h"
+
+// declare the commands
+extern CMD(adduser2);
+extern CMD(autoresponse);
+extern CMD(chattr);
+extern CMD(check);
+extern CMD(deluser);
+extern CMD(listdomain);
+extern CMD(lookup);
+
+#ifdef TEST_DAEMON
+CMD(echo)
+{
+  logcommand(args);
+  mystring msg;
+  for(unsigned i = 0; i < args.count(); i++) {
+    if(i > 0) msg += " ";
+    msg += args[i];
+  }
+  RETURN(ok, msg);
+}
+CMD(fecho)
+{
+  logcommand(args);
+  mystring msg;
+  for(unsigned i = 0; i < args.count(); i++) {
+    if(i > 0) msg += " ";
+    msg += args[i];
+  }
+  RETURN(ok, msg);
+}
+#endif // TEST_DAEMON
+
+//CMD(stat);
+//CMD(statall);
+
+struct dispatch 
+{
+  const char* name;
+  response (*function)(command&, int);
+  unsigned arg_min;
+  unsigned arg_max;
+  bool decode_virtual;
+  //unsigned count;
+};
+
+#define ENTRY(NAME,MIN,MAX,DV) { #NAME , NAME##_cmd , unsigned(MIN), unsigned(MAX), DV }
+dispatch dispatch_table[] = {
+  ENTRY(lookup,       3,  3, true),
+  ENTRY(check,        3,  3, true),
+  ENTRY(chattr,       5, -1, true),
+  ENTRY(adduser2,     5, -1, true),
+  ENTRY(autoresponse, 4,  5, true),
+  ENTRY(deluser,      3,  3, true),
+  ENTRY(listdomain,   2,  2, false),
+#ifdef TEST_DAEMON
+  ENTRY(echo,         0, -1, false), // For testing purposes only
+  ENTRY(fecho,        0, -1, false), // For testing purposes only
+#endif // TEST_DAEMON
+  { "", 0, 0, false, 0 }
+};
+//ENTRY(stat, 1, , false),
+//ENTRY(statall, 0, 0, false),
+
+static dispatch* find_dispatch(mystring name)
+{
+  for(dispatch* ptr = dispatch_table; ptr->function != 0; ptr++) {
+    if(name == ptr->name)
+      return ptr;
+  }
+  return 0;
+}
+
+#if 0
+CMD(stat)
+  // Usage: stat function
+  // Returns: count
+{
+  logcommand(args);
+  const dispatch* ptr = find_dispatch(args[0]);
+  if(!ptr)
+    RETURN(err, "Unknown operation to stat");
+  RETURN(ok, itoa(ptr->count));
+}
+
+CMD(statall)
+  // Usage: statall
+  // Returns: name:count;name:count...
+{
+  logcommand(args);
+  mystring r;
+  for(const dispatch* ptr = dispatch_table; ptr->function != 0; ptr++) {
+    if(!r.empty())
+      r += ";";
+    r += ptr->name;
+    r += ":";
+    r += itoa(ptr->count);
+  }
+  RETURN(ok, r);
+}
+#endif
+
+response dispatch_cmd(command& args, int fd)
+{
+  dispatch* ptr = find_dispatch(args.name());
+  if(ptr) {
+    if(args.count() < ptr->arg_min ||
+       (ptr->arg_max != unsigned(-1) && args.count() > ptr->arg_max))
+      RETURN(bad, "Incorrect number of parameters to command " + args.name());
+    //++ptr->count;
+    if(ptr->decode_virtual) {
+      if(is_local(args[0]))
+	args.replace_first_two(args[1]);
+      else {
+	mystring baseuser(find_virtual(args[0]));
+	if(baseuser.empty())
+	  RETURN(err, "Invalid or unknown domain name: " + args[0]);
+	else if(!args[1])
+	  args.replace_first_two(baseuser);
+	else
+	  args.replace_first_two(baseuser + "-" + args[1]);
+      }
+    }
+    return ptr->function(args, fd);
+  }
+  else
+    RETURN(bad, "Invalid operation");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/listdomain.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,69 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "daemon.h"
+#include "misc/pwentry.h"
+#include "misc/lookup.h"
+
+static bool write_buf(int fd, const char* buf, unsigned length)
+{
+  mystring str(buf, length);
+  response resp(response::ok, str);
+  return resp.write(fd);
+}
+
+CMD_FD(listdomain)
+  // Usage: listdomain domainname password
+{
+  mystring domain = args[0];
+  mystring password = args[1];
+  args[1] = LOG_ADMINPASS;
+  logcommand(args);
+  
+  mystring baseuser(find_virtual(args[0]));
+  if(!baseuser)
+    RETURN(err, "Invalid or unknown domain name: " + args[0]);
+  pwentry* pw;
+  mystring v;
+  if(!lookup_baseuser(baseuser, pw, v))
+    RETURN(err, "Invalid or unknown base user name: " + baseuser);
+  if(!pw->authenticate(password))
+    RETURN(err, "Invalid or incorrect password");
+  
+  state = new saved_state(pw);
+  vpwtable* table = state->domain.table();
+  vpwtable_reader* reader = table->start_read();
+  if(!*reader)
+    RETURN(err, "Base user has no virtual password table");
+
+  if(!write_buf(fd, "", 0))
+    RETURN(err, "Failed while writing initial OK response");
+
+  vpwentry entry;
+  while(reader->get(entry)) {
+    mystring code = entry.to_record();
+    unsigned length = entry.name.length() + 1 + code.length() + 1;
+    char buf[length];
+    memcpy(buf, entry.name.c_str(), entry.name.length()+1);
+    memcpy(buf+entry.name.length()+1, code.c_str(), code.length()+1);
+    if(!write_buf(fd, buf, length))
+      RETURN(err, "Failed while writing list entry");
+  }
+  
+  delete reader;
+  RETURN(ok, "");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/log.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,70 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "daemon.h"
+
+mystring logstr;
+
+extern bool opt_log_all;
+static pid_t pid = 0;
+
+const mystring LOG_PASSWORD = "<password>";
+const mystring LOG_NEWPASS = "<newpass>";
+const mystring LOG_ADMINPASS = "<adminpass>";
+const mystring LOG_MESSAGE = "<message>";
+
+static const char* request_str = "Request: ";
+
+fdobuf& log()
+{
+  if(!pid)
+    pid = getpid();
+  ferr << '[' << pid << "] ";
+  return ferr;
+}
+
+void log(const char* msg)
+{
+  log() << msg << endl;
+}
+
+static void finish(const mystring& str)
+{
+  if(opt_log_all)
+    log() << request_str << str << endl;
+  else
+    logstr = str;
+}
+
+void logcommand(const command& cmd)
+{
+  mystring out = cmd.name();
+  for(unsigned i = 0; i < cmd.count(); i++)
+    out = out + " " + cmd[i];
+  finish(out);
+}
+
+void logresponse(const response& res)
+{
+  if(opt_log_all || !res) {
+    if(!logstr.empty()) {
+      log() << request_str << logstr << endl;
+      logstr = "";
+    }
+    log() << "Completed: " << res.message() << endl;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/log.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,18 @@
+#ifndef VMAILMGRD__DAEMON__LOG__H__
+#define VMAILMGRD__DAEMON__LOG__H__
+
+#include "fdbuf/fdbuf.h"
+#include "command.h"
+#include "misc/response.h"
+
+extern fdobuf& log();
+extern void log(const char*);
+extern void logcommand(const command&);
+extern void logresponse(const response&);
+
+extern const mystring LOG_PASSWORD;
+extern const mystring LOG_NEWPASS;
+extern const mystring LOG_ADMINPASS;
+extern const mystring LOG_MESSAGE;
+
+#endif // VMAILMGRD__DAEMON__LOG__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/lookup.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,78 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "daemon.h"
+#include "log.h"
+#include "misc/lookup.h"
+#include "misc/pwentry_table.h"
+
+response lookup_and_validate(const mystring& fullname,
+			     pwentry* &pw, vpwentry* &vpw,
+			     const mystring& password,
+			     bool mustexist,
+			     bool userpass)
+{
+  if(userpass && !mustexist)
+    RETURN(err, "Internal error -- userpass && !mustexist");
+  mystring virtname;
+  if(!lookup_baseuser(fullname, pw, virtname))
+    RETURN(err, "Invalid or unknown base user or domain");
+  if(!password)
+    RETURN(err, "Incorrect password");
+  bool passok = pw->authenticate(password);
+  if(!passok && !userpass)
+    RETURN(err, "Incorrect password");
+  if(virtname.empty())
+    RETURN(err, "User name does not refer to a virtual user");
+  state = new saved_state(pw);
+  if(mustexist) {
+    vpw = state->domain.lookup(virtname, true);
+    if(!vpw)
+      RETURN(err, "Invalid or unknown virtual user");
+    else if(!passok && !vpw->authenticate(password))
+      RETURN(err, "Incorrect password");
+    else
+      RETURN(ok, "");
+  }
+  else {			// user must not already exist
+    vpw = state->domain.lookup(virtname, true);
+    if(vpw)
+      RETURN(err, "Virtual user already exists");
+    else {
+      vpw = new vpwentry(virtname, "*", 0, 0);
+      vpw->set_defaults(true, true);
+      RETURN(ok, "");
+    }
+  }
+}
+
+CMD_FD(lookup)
+  // Usage: lookup username-virtname password
+  // Result: binary vpwentry data
+{
+  mystring fulluser = args[0];
+  mystring password = args[1];
+  args[1] = LOG_PASSWORD;
+  logcommand(args);
+
+  pwentry* pw;
+  vpwentry* vpw;
+  OK_RESPONSE(lookup_and_validate(fulluser, pw, vpw, password, true, true));
+
+  response(response::ok, vpw->to_record()).write(fd);
+  RETURN(ok, "Wrote virtual user data");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/main.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,194 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <unistd.h>
+#include "cli/cli.h"
+#include "daemon.h"
+
+const char* cli_program = "vmailmgrd";
+const char* cli_help_prefix = "vmailmgr support daemon\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = 0;
+int opt_log_all = true;
+int opt_verbose = false;
+
+// This program is the local server that controls the operation of many
+// parts of this package.
+// It is currently used to handle password checking and virtual user
+// lookups, but will eventually contain the functionality to handle adding
+// and deleting users and aliases, and changing passwords.
+//
+// F<vmailmgrd> logs its activity to standard output, and as such
+// requires its output to be piped through a tool to
+// record those logs, such as F<accustamp> and F<cyclog> (from the
+// F<daemontools> package), or
+// F<splogger> (included with the F<qmail> package).
+
+cli_option cli_options[] = {
+  { 'd', 0, cli_option::flag, 0, &opt_log_all,
+    "Log only requests that fail", 0 },
+  { 'D', 0, cli_option::flag, 1, &opt_log_all,
+    "Log all requests (default)", 0 },
+  { 'v', 0, cli_option::flag, 0, &opt_verbose,
+    "Log non-verbosely (default)", 0 },
+  { 'V', 0, cli_option::flag, 1, &opt_verbose,
+    "Log verbosely", 0 },
+  // Log verbose messages regarding the system's status.
+  // Note that this flag implies C<-D>.
+  {0}
+};
+
+// SEE ALSO
+//
+// vdeliver(1), checkvpw(8)
+
+#define TIMEOUT 1
+
+static inline void die(const char* msg)
+{
+  perror(msg);
+  exit(1);
+}
+
+static void finishreq()
+{
+  alarm(0);
+  close(0);
+  close(1);
+}
+
+static void abortreq(const char* m)
+{
+  logresponse(response(response::bad, m));
+  finishreq();
+}
+
+static RETSIGTYPE handle_hup(int)
+{
+  signal(SIGHUP, handle_hup);
+  log("Stray SIGHUP caught");
+}
+
+static RETSIGTYPE handle_alrm(int)
+{
+  signal(SIGALRM, handle_alrm);
+  abortreq("Timed out waiting for remote");
+  exit(1);
+}
+
+static RETSIGTYPE handle_pipe(int) 
+{
+  signal(SIGPIPE, handle_pipe);
+  abortreq("Connection to client lost");
+  exit(1);
+}
+
+static RETSIGTYPE handle_intr(int)
+{
+  signal(SIGINT, handle_intr);
+  signal(SIGTERM, handle_intr);
+  log("Stray interrupt caught");
+}
+
+bool decode_string(mystring& str, uchar*& buf, ssize_t& buflen)
+{
+  ssize_t length = (buf[0] << 8) | buf[1];
+  buf += 2; buflen -= 2;
+  if(length > buflen)
+    return false;
+  str = mystring((char*)buf, length);
+  buf += length; buflen -= length;
+  return true;
+}
+  
+#define FAIL(MSG) do { abortreq(MSG ", aborting"); return 0; } while(0);
+
+command* decode_data(uchar* ptr, ssize_t length)
+{
+  uchar argcount = *ptr++;
+  --length;
+  mystring cmdstr;
+  if(!decode_string(cmdstr, ptr, length))
+    FAIL("Couldn't decode the command string");
+  if(cmdstr.empty())
+    FAIL("Empty command string");
+  command* cmd = new command(cmdstr, argcount);
+  for(unsigned i = 0; i < argcount; i++) {
+    mystring str;
+    if(!decode_string((*cmd)[i], ptr, length)) {
+      delete cmd;
+      FAIL("Error decoding a command parameter");
+    }
+  }
+  return cmd;
+}
+
+command* read_data() 
+{
+  alarm(TIMEOUT); // avoid denial-of-service by faulty clients
+
+  uchar hdrbuf[3];
+  switch(read(0, &hdrbuf, 3)) {
+  case -1: FAIL("read system call failed or was interrupted");
+  case 3: break;
+  default: FAIL("Short read while reading protocol header");
+  }
+  if(hdrbuf[0] != 2)
+    FAIL("Invalid protocol from client");
+  ssize_t length = (hdrbuf[1] << 8) | hdrbuf[2];
+  uchar buf[length];
+  if(read(0, buf, length) != length)
+    FAIL("Short read while reading message data");
+  alarm(0);
+  return decode_data(buf, length);
+}
+
+int cli_main(int, char**)
+{
+  if(opt_verbose)
+    opt_log_all = true;
+
+  signal(SIGALRM, handle_alrm);
+  signal(SIGPIPE, handle_pipe);
+  signal(SIGINT, handle_intr);
+  signal(SIGTERM, handle_intr);
+  signal(SIGHUP, handle_hup);
+  signal(SIGQUIT, handle_intr);
+  
+  if(opt_verbose)
+    log("Accepted connection");
+  command* cmd = read_data();
+  if(cmd) {
+    response resp = dispatch_cmd(*cmd, 1);
+    logresponse(resp);
+    alarm(TIMEOUT);
+    if(!resp.write(1))
+      abortreq("Error writing response");
+    finishreq();
+    delete cmd;
+  }
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/state.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,37 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <unistd.h>
+#include "state.h"
+
+saved_state::saved_state(const pwentry* pw)
+  : domain(*pw), oldconfig(config)
+{
+  status = !setgid(pw->gid) &&
+    !setuid(pw->uid) &&
+    !chdir(pw->home.c_str());
+  if(ok())
+    config = &domain.config;
+}
+
+saved_state::~saved_state()
+{
+  if(ok()) {
+    config = oldconfig;
+  }
+}
+
+saved_state* state = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/state.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,52 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef VMAILMGR__STATE__H__
+#define VMAILMGR__STATE__H__
+
+#include <sys/types.h>
+#include "misc/pwentry.h"
+#include "vdomain/vdomain.h"
+
+class saved_state
+{
+  bool status;
+
+  // Make these private so they can't be called
+  saved_state();
+  saved_state(const saved_state&);
+public:
+  vdomain domain;
+  const configuration* oldconfig;
+
+  saved_state(const pwentry* pw);
+  ~saved_state();
+  
+  bool ok() const
+    {
+      return status;
+    }
+  bool bad() const
+    {
+      return !status;
+    }
+};
+
+extern saved_state* state;
+
+//#define CHANGE_STATE(PW) do{ saved_state state(PW); if(state.bad()) RETURN(err, "Can't change state"); }while(0)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/vmailmgrd.8	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,247 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH vmailmgrd 8 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vmailmgrd \- vmailmgr support daemon
+.SH "SYNOPSIS"
+\fBvmailmgrd\fR
+[\fB\-d\fR]
+[\fB\-D\fR]
+[\fB\-v\fR]
+[\fB\-V\fR]
+.SH "DESCRIPTION"
+This program is the local server that controls the operation of many
+parts of this package.
+It is currently used to handle password checking and virtual user
+lookups, but will eventually contain the functionality to handle adding
+and deleting users and aliases, and changing passwords.
+.PP
+\fIvmailmgrd\fR logs its activity to standard output, and as such
+requires its output to be piped through a tool to
+record those logs, such as \fIaccustamp\fR and \fIcyclog\fR (from the
+\fIdaemontools\fR package), or
+\fIsplogger\fR (included with the \fIqmail\fR package).
+.SH "OPTIONS"
+.Ip "\fB\-d\fR" 8
+Log only requests that fail.
+.Ip "\fB\-D\fR" 8
+Log all requests (default).
+.Ip "\fB\-v\fR" 8
+Log non-verbosely (default).
+.Ip "\fB\-V\fR" 8
+Log verbose messages regarding the system's status. Note that this flag implies \f(CW-D\fR.
+.SH "SEE ALSO"
+\fIvdeliver\fR\|(1), \fIcheckvpw\fR\|(8)
+.SH "AUTHORS"
+Bruce Guenter <bruceg@em.ca>
+
+.rn }` ''
+.IX Title "vmailmgrd 8"
+.IX Name "vmailmgrd - vmailmgr support daemon"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "OPTIONS"
+
+.IX Item "\fB\-d\fR"
+
+.IX Item "\fB\-D\fR"
+
+.IX Item "\fB\-v\fR"
+
+.IX Item "\fB\-V\fR"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHORS"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/vmailmgrd.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,87 @@
+<HTML>
+<HEAD>
+<TITLE>vmailmgrd - vmailmgr support daemon</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#OPTIONS">OPTIONS</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#AUTHORS">AUTHORS</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vmailmgrd - vmailmgr support daemon
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
+<P>
+<STRONG>vmailmgrd</STRONG>
+[<STRONG>-d</STRONG>] [<STRONG>-D</STRONG>] [<STRONG>-v</STRONG>] [<STRONG>-V</STRONG>]
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This program is the local server that controls the operation of many parts
+of this package. It is currently used to handle password checking and
+virtual user lookups, but will eventually contain the functionality to
+handle adding and deleting users and aliases, and changing passwords.
+
+<P>
+<EM>vmailmgrd</EM> logs its activity to standard output, and as such requires its output to be
+piped through a tool to record those logs, such as <EM>accustamp</EM> and <EM>cyclog</EM> (from the
+<EM>daemontools</EM> package), or
+<EM>splogger</EM> (included with the <EM>qmail</EM> package).
+
+<P>
+<HR>
+<H1><A NAME="OPTIONS">OPTIONS</A></H1>
+<DL>
+<DT><STRONG><A NAME="item__d">-d</A></STRONG><DD>
+<P>
+Log only requests that fail.
+
+<DT><STRONG><A NAME="item__D">-D</A></STRONG><DD>
+<P>
+Log all requests (default).
+
+<DT><STRONG><A NAME="item__v">-v</A></STRONG><DD>
+<P>
+Log non-verbosely (default).
+
+<DT><STRONG><A NAME="item__V">-V</A></STRONG><DD>
+<P>
+Log verbose messages regarding the system's status. Note that this flag
+implies <CODE>-D</CODE>.
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>vdeliver(1),</CODE> <CODE>checkvpw(8)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="AUTHORS">AUTHORS</A></H1>
+<P>
+Bruce Guenter &lt;<A HREF="mailto:bruceg@em.ca">bruceg@em.ca</A>&gt;
+
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/daemon/vmailmgrd.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,61 @@
+=head1 NAME
+
+vmailmgrd - vmailmgr support daemon
+
+=head1 SYNOPSIS
+
+B<vmailmgrd>
+[B<-d>]
+[B<-D>]
+[B<-v>]
+[B<-V>]
+
+
+=head1 DESCRIPTION
+
+This program is the local server that controls the operation of many
+parts of this package.
+It is currently used to handle password checking and virtual user
+lookups, but will eventually contain the functionality to handle adding
+and deleting users and aliases, and changing passwords.
+
+F<vmailmgrd> logs its activity to standard output, and as such
+requires its output to be piped through a tool to
+record those logs, such as F<accustamp> and F<cyclog> (from the
+F<daemontools> package), or
+F<splogger> (included with the F<qmail> package).
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-d>
+
+Log only requests that fail.
+
+=item B<-D>
+
+Log all requests (default).
+
+=item B<-v>
+
+Log non-verbosely (default).
+
+=item B<-V>
+
+Log verbose messages regarding the system's status. Note that this flag implies C<-D>.
+
+=back
+
+=head1 SEE ALSO
+
+
+vdeliver(1), checkvpw(8)
+
+
+
+=head1 AUTHORS
+
+Bruce Guenter <bruceg@em.ca>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/ChangeLog-pre-0.70	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,517 @@
+1998-03-19  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* vmailmgrd.pod: Documented the -d and -D options for logging.
+
+	* daemon/log.cc (finish): It is not correct to un-freeze a string
+	stream while a character pointer to its contents is still in use.
+	Moved the "out.freeze(0)" call to after the contents were used.
+
+1998-03-15  Bruce Guenter  <bguenter@hal.qcc.sk.ca>
+
+	* lib/config.h: Added explanations of the various definitions, and
+	added the definitions DO_SHADOW and MAILDIR_ARG_STR.
+
+	* lib/pwentry_getpw.cc: #include the config.h file, which may
+	define DO_SHADOW.
+
+	* commands/checkvpw.cc (find_maildir): Use the configuration macro
+	MAILDIR_ARG_STR instead of the hard coded string "maildir".
+
+1998-03-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/checkvpw.cc (getdata): Wrote some small modifications
+	here to make it more correct and slightly more efficient.
+
+1998-03-12  Bruce Guenter  <bguenter@hal.qcc.sk.ca>
+
+	* commands/checkvpw.cc (authenticate): Coded the server call to
+	use the convenience constructor.
+
+	* commands/vdeliver.cc (main): Coded the server call to use the
+	convenience constructor.
+
+	* lib/server.cc (server_call): Added several convenience
+	constructors, taking 0-4 string arguments.
+
+1998-03-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Released version 0.69pre9
+
+	* commands/vadduser.cc (setup): Initialize the random number
+	generator.
+
+	* commands/vpasswd.cc (main): Initialize the random number
+	generator before changing passwords.  This helps to prevent
+	identical "salt"s in the passwords.
+
+	* commands/vadduser.cc (setup): Added a check for the
+	'.qmail-default' file, and print a short message explaining how to
+	create it if it does not exist.
+
+1998-03-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeliver.cc (exit_msg): Forgot to write a trailing
+	newline in the exit messages.  Fixed.
+
+1998-03-10  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeluser.cc (main): Changed the response messages to
+	look more like the other command programs.
+
+	* lib/Makefile: Added rules to build the common library as a
+	shared object, libvmailmgr.so.$(libversion), to which all the
+	other programs link.
+
+	* version: Added new version variables: libversion and soversion,
+	used for building versioned shared objects.
+
+	* lib/passwdfn.cc (getpasswd): Fixed the problem that would cause
+	an error message about an empty password to be printed if the
+	passwords were different.
+
+	* commands/vpasswd.cc (main): Removed the server call in this
+	program and made it use vuser_chpass instead.
+
+	* lib/vuser_chpass.cc (vuser_chpass): Wrote this pair of routines
+	which change the password of a user in a virtual password table.
+
+	* daemon/chpass.cc (CMD(chpass)): Modified to use vuser_chpass.
+
+1998-03-09  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/chpass.cc (CMD(chpass)): Converted to use autodelete.
+
+	* daemon/adduser.cc (CMD(adduser)): Converted to use autodelete.
+
+1998-03-08  Bruce Guenter  <bguenter@hal.qcc.sk.ca>
+
+	* Released version 0.69pre8
+
+	* lib/vuser_lookup.cc (vuser_lookup): Converted to use autodelete.
+
+	* lib/vuser_delalias.cc (vuser_delalias): Converted to use autodelete.
+
+	* lib/vuser_deluser.cc (vuser_deluser): Converted to use autodelete.
+
+	* lib/pwentry_delpw.cc (delpw): Fixed the same problem as in putpw.
+	(delpw): Fixed the typo in creating the output file (output file
+	name is in variable 'copyfile', not 'file').
+
+	* lib/pwentry_putpw.cc (putpw): istream.getline should be used
+	instead of istream.get which doesn't discard the newline.
+
+	* lib/vuser_add.cc (bad_chars): Removed the check for the
+	directory separator in this routine, as '/' is a valid character
+	in both password fields and e-mail addresses.
+
+1998-03-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* vaddalias.pod: Updated the document to reflect the below change.
+
+	* commands/vaddalias.cc (main): Modified the user lookup code to
+	skip looking up a local user if the address contains a hostname
+	(preceeded by an at sign (@)).
+
+	* lib/mystring.cc (find): Modified this routine to add an "offset"
+	parameter at which to start the search.
+
+1998-02-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.69pre7
+
+	* commands/checkvpw.cc (main): If the environment variable
+	TCPLOCALHOST is not set, get the host name from gethostname(3).
+
+	* daemon/main.cc (abortreq): Now generates a temporary response
+	(with code=bad) and calls finishreq.
+	(finishreq): Wrote this routine which logs a response and closes
+	the connection.
+	(main): Print out a message regarding the status of logging.
+	(parse_options): Added code to parse the command line options.
+
+	* daemon/log.cc (logresponse): Added this routine that optionally
+	logs both the command and the response if either the response
+	indicates an error or the program is logging all responses.
+	Also set up all the other routines to log to a string which is
+	only optionally logged given the above conditions.
+
+1998-02-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/log.cc: Wrote various 'logcommand' routines into this file.
+
+1998-02-21  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (handle_connection): Removed command logging from
+	this central location and distributed it to all the command
+	modules, so that sensitive information (passwords) can be sensibly
+	omitted.
+
+	* commands/checkvpw.cc (strcasestr): Fixed bug that failed to
+	match 'needle' in the 'haystack' if the occurrence of 'needle' was
+	followed by non-nul characters.
+
+	* commands/vdeliver.cc (main): Now reports error messages to
+	stdout, so that bounce messages will contain some description of
+	what goes wrong.
+
+	* commands/checkvpw.cc (main): Fixed bug in setting maildir for
+	virtual users: argument maildirarg+1 was being set, but maildirarg
+	is already incremented.
+
+1998-02-19  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/qmail.cc (find_virtual): Converted to fstream I/O.
+
+	* lib/pwentry_putpw.cc (putpw): Converted to fstream I/O.
+
+	* lib/pwentry_getpw.cc (getpw_byname): Converted to fstream I/O.
+
+	* lib/pwentry_delpw.cc (delpw): Converted to fstream I/O.
+
+	* lib/passwdfn.cc: Removed a pile of unused code.
+
+	* lib/mystring.h (operator<<): Added this operator which provides
+	ostream support for class mystring.
+
+1998-02-18  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* After much thought and time spent developing the fdio classes, I
+	discovered that I was just re-developing the standard C++ iostream
+	classes.  So, all further I/O will be based on iostreams, and all
+	use of the fdio classes will be converted.
+
+	* vmailmgr.pod: Pulled this manual page, describing the general
+	overview of the vmailmgr package, from the vmailmgr.texi
+	file.  There is now no content in the vmailmgr.texi file, and it
+	is removed from the package.
+
+	* vdelalias.pod: Pulled this manual page for vdelalias.
+
+	* vaddalias.pod: Pulled this manual page for vaddalias.
+
+	* vdeluser.pod: Pulled this manual page for vdeluser.
+
+	* vadduser.pod: Pulled this manual page for vadduser.
+
+	* vpasswd.pod: Pulled this manual page for vpasswd.
+
+1998-02-17  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* checkvpw.pod: Pulled this manual page for checkvpw from
+	vmailmgr.texi.
+
+	* vmailmgrd.pod: Wrote this manual page for vmailmgrd.
+
+	* vdeliver.pod: Wrote this manual page for vdeliver and removed
+	the section for vmailmgr.texi pertaining to vdeliver.
+
+1998-02-16  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/lookup.cc (CMD(lookup)): Removed the code to check the
+	arguments.
+	(CMD(lookup)): Fixed a logic flaw that reported virtual users with
+	an erroneously empty destination field as valid users.
+
+	* daemon/check.cc (CMD(check)): Removed the code to check the
+	arguments.
+
+	* daemon/daemon.h (class command): The array of arguments is now
+	an array of pointers to mystring instead of an array of mystring's.
+
+	* daemon/dispatch.cc (dispatch_cmd): Added code to handle virtual
+	domain parsing and argument counting.
+
+	* daemon/command.cc (replace_first_two): Wrote this routine to
+	help consolidate the virtual-domain parsing routines into
+	dispatch_cmd.
+
+	* released version 0.69pre6
+
+	* daemon/main.cc (abortreq): Removed the abortreq/0 routine.
+
+	* commands/vadduser.cc: Adapted this program to use the fdio library.
+
+	* commands/vaddalias.cc (main): Adapted this program to use the
+	fdio library, and fixed the logic problem that prevented any alias
+	from being added.
+
+	* lib/pwentry_delpw.cc (delpw): Added this routine to delete a
+	password entry.
+
+	* lib/pwentry.h: turned the addpw/setpw macros into inline routines.
+
+	* commands/vdeluser.cc (main): Adapted this program to use the
+	vuser_deluser routine and fdio.
+
+	* commands/vdelalias.cc (main): Adapted this program to use the
+	vuser_delalias routine and fdio.
+
+	* lib/vuser_delalias.cc (vuser_delalias): Wrote this routine to
+	delete an alias.
+
+	* lib/vuser_deluser.cc (vuser_deluser): Adapted this routine from
+	vdeluser.cc to delete a user and its maildir.
+
+	* lib/vuser_add.cc (bad_chars): Added the directory separator
+	('/') to the list of bad characters.
+
+	* daemon/dispatch.cc (struct dispatch ): Started to add support
+	for a unified parameter decoder.
+
+	* lib/qmail.cc: Removed the 'dot_qmail_name' and 'valid_name'
+	routines, which are no longer necessary.
+
+1998-02-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/fdio_base.cc (fdstream): Remove the trigger character
+	argument to the constructors, set the trigger to '\n' if the file
+	descriptor is a tty.
+
+1998-02-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/fdio.h (class fdistream): Started writing the input class.
+
+	* daemon/main.cc (logcommand): Added a special case to blank out
+	the last argument (the password) for "check" commands.
+
+	* daemon/lookup.cc (lookup_maildir): Converted to use autodelete.
+
+	* daemon/main.cc (main): Added a handler for SIGHUP (currently
+	does nothing, will eventually signal to clear all cached tables).
+
+	* commands/checkvpw.cc (find_maildir): Fixed logic negation problem.
+	(main): Fixed problem in call to lookup_maildir (hostname/username
+	arguments were out of order).
+
+1998-02-10  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/checkvpw.cc (lookup_maildir): Wrote this routine to
+	explicitly lookup the maildir of a user.
+	(authenticate): Removed the code to parse the maildir field out of
+	the response message from "check".
+	(main): Recoded to find the maildir argument, use it as the
+	default maildir, and only replace that argument in the case of
+	authenticating a virtual user.
+
+	* daemon/lookup.cc (CMD): The main command now takes similar
+	arguments to all the other commands which handle virtual domains,
+	and returns either the "destination" field for a virtual user or
+	an empty string for a real user.
+
+	* daemon/check.cc (check): Removed the code to lookup the
+	maildir.  The check command no longer reports maildir
+	information.  This happens to make this routine a great deal
+	simpler.
+	(check): Use autodelete<T> for basepw and virtpw.
+	(CMD): Recoded the main command routine to check is_local before
+	find_virtual.
+
+	* lib/autodelete.h (class autodelete ): Wrote this (template)
+	class to automatically delete a pointer when it is goes out of
+	scope.
+
+	* lib/config.h: Added new define, DEFAULT_MAILDIR, that represents
+	the default maildir to use if none is given.
+
+1998-02-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.69pre5
+
+	* lib/fdio_out.cc (write): Handle unbuffered reads/writes.
+	(write): Corrected handling of triggerchar.
+
+	* lib/fdio.h (class fdstream): Add setbuffer and settrigger
+	methods to setup or reset the buffering and trigger characters.
+
+	* daemon/main.cc (msg): Rewrote these routines to use the new fdio
+	classes.
+
+	* lib/fdio_out.cc: Wrote this file, containing the output class
+	fdostream.
+
+	* lib/fdio_base.cc: Wrote this file, containing the base I/O class
+	fdstream.
+
+1998-02-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/pwentry_getpw.cc (getpw_byname): Fixed shadow password
+	support (password field is sp_pwdp, not spw_pwdp).
+
+	* lib/response_message.cc (codestr): Wrote this function that
+	returns a string version of the response code.
+
+	* daemon/main.cc (handle_connection): Modified to print out more
+	useful information for logging: request contents and responses.
+
+	* commands/vadduser.cc (add_user,add_alias): Check to make sure
+	the user or alias does not exist before adding it.
+
+	* commands/vaddalias.cc (main): Rewrote this program to use the
+	vuser_* routines.
+
+	* daemon/lookup.cc (lookup_maildir): Rewrote this function to use
+	vuser_lookup.
+
+	* lib/vuser_lookup.cc (vuser_lookup): Moved this function out of
+	daemon/lookup.cc.
+
+1998-02-06  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.69pre4
+	
+	* commands/vadduser.cc (add_user): Completed rewriting this
+	program to use the vuser_* routines.
+
+	* lib/pwentry_getpw.cc (getpw_byname): Added support for shadow
+	passwords (untested).
+
+	* lib/pwentry_setpw.cc (putpw): Fixed bug in string comparison:
+	when the name to add is longer than the name in the password file,
+	the extra characters are not compared.
+
+	* lib/vuser_add.cc (vuser_addalias): Wrote this routine, adds an
+	alias to a password file.
+	(vuser_add): Modified this routine to create a maildir only if the
+	maildir parameter is not empty.  Also, check if the name and
+	password contain invalid characters (currently only checks for ':'
+	and whitespace).
+
+	* commands/testclient.cc (main): Rewrote to use the new
+	response::message routine.
+
+	* lib/response_message.cc (message): Wrote this routine which
+	returns the msg field with a prefix tag corresponding to the code
+	field.
+
+	* lib/response.h (struct response): Added operator!, returns true
+	if the response is not ok.
+
+	* lib/vuser_add.cc (vuser_add): Added new vuser_add routine which
+	builds the vpwentry and passes it to the other vuser_add routine.
+
+1998-01-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/vuser_add.cc (vuser_add): Modified this routine to call
+	addpw instead of setpw.
+
+	* lib/pwentry.h: Renamed setpw to putpw and made two new macros,
+	setpw and addpw, that call it.
+
+	* lib/pwentry_setpw.cc (putpw): Added support to setpw to only add
+	(no overwrite) new entries, and renamed it to putpw.
+
+1998-01-28  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/vuser_add.cc (vuser_add): Moved part of adduser from
+	daemon/adduser.cc here, with the name vuser_add.
+
+	* daemon/chpass.cc (chpass): Rewrote to use the new saved_uidgid
+	class.
+
+	* commands/vpasswd.cc (main): Rewrote to use the new response
+	class.
+
+	* commands/vdeliver.cc (main): Rewrote to use the new response
+	class.
+
+	* commands/testclient.cc (main): Rewrote to use the new response
+	class.
+
+	* commands/checkvpw.cc (authenticate): Rewrote to use new response
+	class.
+
+	* lib/server.h: Removed the class server_response, which was
+	functionally identical to class response.
+
+	* lib/pwentry_getpw.cc (getpw_byname): Moved the implementation of
+	this routine into a separate file.
+
+	* lib/pwentry_setpw.cc (setpw): Moved the implementation of this
+	routine into a separate file.
+	(setpw_pass): Commented out this routine, for now.
+
+	* Moved pwcrypt.h, pwcrypt.cc, pwentry.h, pwentry.cc into lib.
+
+	* lib/response_write.cc (write): Moved the implementation of
+	response::write into this file.
+
+	* lib/response.h (struct response ): Moved this class from
+	daemon/daemon.h into this file, as I plan to use it in some
+	non-daemon applications.
+
+	* daemon/uidgid.h (class saved_uidgid): Moved the
+	push_uidgid/pop_uidgid behavior into this class, which allows me
+	to let C++ automatically "pop" the uid/gid state when a routine
+	exits.
+
+1998-01-27  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vadduser.cc: Started modifying this program to call the
+	server.
+
+	* daemon/adduser.cc (adduser): Finished implementing this function.
+
+	* daemon/lookup.cc (lookup_maildir): Modified the lookup logic
+	such that an empty destination field is invalid.
+
+	* daemon/pwentry.cc (putpw): Fixed to add a newline at the end of
+	the entry.
+	(setpw): Fixed logic error with the final return code.
+
+	* daemon/pwcrypt.cc (encrypt): Wrote this routine which generates
+	a random salt and encrypts the password using this new random
+	salt.
+
+	* daemon/chpass.cc (chpass): Simplify matters by resetting the
+	password in the vpw structure and calling setpw instead of
+	setpw_pass.
+
+	* daemon/pwentry.cc: Moved the crypt_cmp routine into its own
+	file, pwcrypt.cc.
+
+1998-01-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/dispatch.cc (CMD(statall)): Wrote this routine to return
+	stats on all the routines in the dispatch table.
+
+	* daemon/adduser.cc (adduser): Started to write this module which
+	adds a virtual account to a domain.
+
+	* daemon/chpass.cc (chpass): modified to use the new userlookup
+	and pwentry functions.
+
+	* daemon/check.cc (check): modified to use the new userlookup.
+
+	* daemon/lookup.cc (userlookup): modified to get the virtual
+	password table entry if it exists, using the new pwentry
+	functions.
+	(lookup_maildir): modified to use the new pwentry functions.
+
+	* daemon/pwentry.cc (getpw_byname/2): Written, looks up a global
+	password entry.
+	(getpw_byname/3): Written, looks up a virtual password entry.
+	Note that the return value from all the 'getpw*' functions must be
+	deleted.
+	(setpw): Written, sets an entry in a virtual password file.
+	(setpw_pass): Written, sets the password in a virtual password
+	file.
+
+	* daemon/pwentry.h (struct pwentry, vpwentry): Wrote this header
+	to encapsulate global and virtual password file lookups.
+
+	* lib/passwdfn.cc: Commented out all the password file
+	manipulation functions.
+
+	* lib/passwdfn.h: Commented out all the password file manipulation
+	functions.
+
+1998-01-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeliver.cc: Remove the duplicate definitions of
+	functions provided in the "stat_fns" header file.
+
+	* Changed the package's name to 'vmailmgr' (Virtual MAIL
+	ManaGeR).  It is quite readily apparent that this package has
+	evolved into something much larger than just a password checking
+	program.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/ChangeLog-pre-vmailmgr	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,442 @@
+1998-01-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/vdeliver.cc (main): Added support for optionally adding
+	the From, Delivered-To:, and Return-Path: line to the start of the
+	output mail, either to a file or to qmail-inject (which omits the
+	From line).
+
+1998-01-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* commands/checkvpw.cc (authenticate): Revised the logic to only
+	validate the password if an 'ok' code is returned (was previously
+	the default case), and to indicate bad data otherwise.
+
+	* commands/testclient.cc (main): Added a case for the new econn
+	return code.
+
+	* daemon/lookup.cc (CMD(lookup)): Wrote this routine to lookup a
+	virtual user's delivery instructions.  Returns one of: &address,
+	&address@hostname, /full/path/to/maildir, or ./maildir
+
+	* daemon/dispatch.cc (CMD(stat)): Added a new field to the
+	dispatch table, count, which is used to count the number of times
+	that function has been invoked.  The new function, stat, can be
+	used to return this count on a per-function basis.
+
+	* commands/vdeliver.cc (main): If the call caused a connection
+	error, defer the message (return 111).
+
+	* lib/server.cc (call): Return 'econn' when either building the
+	connection, sending, or receiving data fails.
+
+	* lib/server.h (struct server_response): Added another error code
+	'econn', used to denote an error with the connection itself.
+
+	* lib/mystring.h (class mystring): Changed the 'nil' constant to
+	'const char*' type from 'mystring' type.  This avoids the need for
+	a special protected constructor just for this object, and more
+	accurately reflects its purpose as a placeholder buffer for empty
+	strings.
+	(operator!=): Revised this operation to test if the string to
+	which this is being compared is a NULL pointer.
+
+	* commands/vdeliver.cc: Wrote this program to be inserted in a
+	.qmail-default file, to serve as the delivery agent for all the
+	addresses.
+
+	* lib/mystring.cc (dup): Wrote dup/5 routine for combining 5
+	strings.
+
+1998-01-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* daemon/main.cc (main): Fixed bug in socket bind call to use
+	correct length value computed by SUN_LEN macro.  Still need to
+	actually allocate the memory for the sockaddr_un with malloc
+	instead of relying on the buffer for sun_path being long enough.
+
+	* lib/server.cc (connect): Fixed bug in socket connect call to use
+	correct length value computed by SUN_LEN macro.
+
+	* Released version 0.69pre1 pre-release.
+
+	* commands/checkvpw.cc: Moved the definitions of the FAIL_* macros
+	into this file from lib/debug.h
+
+	* daemon/check.cc (check): Fixed several logic bugs.
+
+	* src/checkvpw.cc (main): Rewrote this program to use the 'check'
+	feature of the daemon.
+
+	* daemon/main.cc (handle_connection): Print out a message when the
+	request completes as well as when it is started.
+
+	* daemon/chpass.cc: Fixed some one-off bugs in the command-line
+	handling.
+
+	* src/vpasswd.cc (main): Rewrote this program to be a simple
+	server call stub to the 'chpass' feature.
+
+	* checkvpw.texi: Started reorganizing this document for the
+	inclusion of documentation on the daemon program.
+
+	* lib/server.h (class server_call): Removed the 'msg' class -- it
+	was causing all sorts of headaches from memory deallocation, and
+	was originally implemented as a premature optimization.
+
+1998-01-21  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/debug.h: Added trace, traceptr, and tracestr functions, to
+	trace the flow of class methods.
+
+	* lib/mystring.cc: Introduced the "nil" string -- a constant
+	statically allocated empty string.  Duplicating an empty string or
+	a null pointer duplicates the pointer to this nil string, instead
+	of allocating more memory.  Freeing the nil string is not allowed.
+
+1998-01-18  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Started rewriting the protocol used to communicate between the
+	client and server to be more efficient.  See doc/protocol.txt for
+	a very sketchy protocol definition.
+	
+	* daemon/check.cc (check): Wrote this routine to do password
+	checking, copied mostly from src/checkvpw.cc.
+
+	* src/testclient.cc: Wrote this program to serve as a test client
+	to the server, to test all the data paths through the client
+	library and the server functions without depending on the
+	implementation of the other programs.
+
+	* lib/server.h (class server_call): Wrote the classes in this file
+	and lib/server.cc to encapsulate a call to the server and its
+	response.
+
+1998-01-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Started work on the checkvpw daemon -- a user-space server that
+	handles all the real functionality of all the other programs via a
+	UNIX domain socket.  It currently handles checking passwords (for
+	checkvpw) and changing passwords (for vpasswd).
+
+	* lib/mystring.cc (operator+): wrote a new copy of this that takes
+	a 'const char*' second parameter.
+	(*): Rewrote several of the routines that return a new mystring to
+	use the 'named return value' extension of gcc (if being compiled
+	under gcc).
+
+1998-01-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/mystring: Added or modified several routines that take
+	"const char*" instead of "const mystring&" as parameters, to
+	prevent the unnecessary spurious creation of temporary
+	mystring's.
+
+1998-01-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/passwdfn.cc (fsetpasswd): This new routine encrypts the
+	given password and sets it in the named password file.
+
+	* src/vpasswd.cc (main): Require that the new password is not the
+	same as the newly entered password.
+	(main): Use the newly written 'fssetpasswd' routine.
+
+	* lib/mystring.cc (append): Wrote this method to support string
+	concatenation using "+" and "+=" operators.
+
+	* lib/cgi-base.h (class CGI): Started this class to provide helper
+	functions for CGI applications.
+
+1998-01-10  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* lib/cgi-base.cc (main): Wrote this main routine of all CGI
+	programs; calls cgi_main with the CGI arguments as a parameter.
+	(main): Print an error message and don't call cgi_main if there
+	was an error fetching the CGI arguments.
+
+	* lib/cgi-base.h (class CGIArgs ): Wrote this class to encapsulate
+	the list of arguments or input items on a CGI form.
+
+	* lib/mystring.h (class mystring): Wrote a default constructor.
+	Wrote operator!, returns true if the string is empty.
+
+	* Reorganized the directory structure: generic library files are
+	in "lib", program sources are in "src", and CGI sources are in
+	"CGI".
+
+	* src/*.h: Prepended "CHECKVPW__" to the file identifier macro in
+	most of the header files
+
+1998-01-06  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* vpasswd.cc (main): Changed occurences of "passwd" to use the
+	PASSWORD_FILE define.
+
+1998-01-05  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* spec (Requires): checkvpw does not really "require" qmail, it's
+	just the only thing that currently uses it, so I removed this
+	requirement.
+
+	* released version 0.65-1
+
+	* Makefile: makefile included in the distributed sources does not
+	contain the sections specific to building the distribution.
+
+	* qmail.cc (find_virtual): fixed bug in search logic
+
+1998-01-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* mystring.cc (operator=): written
+
+	* checkvpw.texi (checkvpw): updated the documentation to reflect
+	the changes listed below.
+
+	* qmail.cc (find_virtual): modified the logic searching for a
+	virtual domain to match that of qmail -- wildcards in the
+	virtualdomains file are not automatic, but are represented by a
+	leading '.' in the host name.  The new search is also
+	non-recursive and only reads the virtualdomains file once.
+
+1998-01-02  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* checkvpw.cc (main): If the user name contains a '@' symbol,
+	treat the string following the '@' as the host name, and the
+	string preceding the '@' as the username within that host's
+	virtual domain.
+
+	* mystring.h (class mystring): modified the subst, lower, and
+	upper methods to return a new (modified) mystring instead of
+	modifying the current string.
+	(class mystring): wrote the 'left', 'right', and 'sub' methods,
+	which return portions of the string.
+	(class mystring): wrote the 'find' method, finds a single
+	character in the string
+
+	* Makefile: patched for glibc to automatically add the separate
+	"crypt" library to the link stage if it is detected in its
+	"normal" location (/usr/lib/libcrypt.*)
+
+1997-12-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* mystring.cc: recoded "dup" functions to handle NULL pointers as
+	empty strings
+
+1997-12-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* checkvpw.cc (main): Changed both the normal and the virtual
+	authentication case to call the same authentication routine.  This
+	allows a user to enter "userid-virtualuser" as a pop-3 username
+	that will access user "virtualuser" in the mail domain that
+	"userid" controls.
+
+Thu Nov 27 22:07:42 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* qmail.cc (find_virtual): moved into qmail.cc from checkvpw.cc
+
+Wed Nov 26 11:52:24 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.64-1
+
+	* vdeluser.cc (main): convert user names to lower case
+
+	* vdelalias.cc: removed routine dot_qmail_name (duplicates qmail.cc)
+
+	* vpasswd.cc (main): convert the user name to lower case
+
+	* vadduser.cc (set_password): convert the user name to lower case
+	(main): various conversions to ensure usernames are all lower case
+
+	* qmail.cc (dot_qmail_name): make the .qmail file name lowercase
+
+	* checkvpw.cc (struct auth_data): convert the name to lower case
+	on input
+
+	* mystring.cc (tolower,toupper): written, convert strings to all
+	upper or lower case
+
+Thu Nov 20 13:56:55 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.63-1
+
+	* vdeluser.cc (dot_qmail_rm): removed the code to strip trailing
+	whitespace -- the trailing \n is already in the search string
+	(dot_qmail_rm): provide more information on what files are being
+	removed
+	(main): fixed a bug that would cause mail directory for only the
+	first user named to be removed
+
+Tue Nov 18 12:32:47 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.62-1
+
+	* vdeluser.cc (dot_qmail_rm): added code to strip trailing
+	whitespace from the string returned by fgets
+
+	* passwdfn.cc (getpasswd_stdin): added code to strip trailing
+	whitespace from the string returned by fgets
+
+	* checkvpw.cc (auth_virtual): fixed a whole series of one-off bugs
+	that would cause authorization to fail in certain cases
+	(find_virtual_recurse): added code to strip trailing whitespace
+	from virtual prefixes
+
+Thu Nov 13 11:17:02 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* vadduser.cc (check_names): now checks for the existance of
+	.qmail files
+
+	* released version 0.61-1
+
+	* passwdfn.cc (getpasswd): split getpasswd() into two more
+	functions, getpasswd_stdin() and getpasswd_interactive(), to avoid
+	using the default mystring constructor
+
+	* mystring.h (class mystring): removed default constructor -- it
+	appears to have been causing segmentation faults
+
+Wed Nov 12 09:20:04 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* passwdfn.cc (getpasswd): fixed length of fgets from 8 to 9
+
+	* released version 0.60-1
+
+	* Updated the documentation to reflect the change in password
+	handling.
+
+	* mystring.h (class mystring): added a default constructor
+
+	* vpasswd.cc (main): changed to use getpasswd
+
+	* vadduser.cc (set_password): changed to use getpasswd
+
+	* passwdfn.cc (getpasswd): written, gets a password from the
+	user.  If stdin is a tty, then it uses the prompts and getpass()
+	function, otherwise it just reads the password with no prompts.
+
+	* released version 0.59-1
+
+	* vpasswd.cc (main): bugfix: manually duplicate all the fields of
+	pw into newpw, using strdup on strings.  This avoids future calls
+	to getpwent overwriting the existing data (the strings in the pw
+	structure are pointers to static data).
+
+Mon Sep 22 13:47:16 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.58-1
+
+	* qmail.cc: this file will include some QMail specific functions
+	(dot_qmail_name): moved into qmail.cc from vaddalias and vadduser
+
+	* vadduser.cc (main): make sure all names are valid
+
+	* vaddalias.cc (main): make sure the aliases are valid before
+	creating them
+
+Fri Sep 19 12:01:04 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.57-1
+
+	* checkvpw.texi: updated documentation for vaddalias and vdelalias
+
+	* vdelalias.cc: wrote vdelalias to delete aliases
+
+	* vaddalias.cc: wrote vaddalias to add a new alias to an existing
+	user
+
+	* stat_fns.h (is_file): added
+
+Thu Sep 18 09:05:46 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* tweaked root-level Makefile to clean up after building a
+	distribution
+
+	* released version 0.56-1
+
+	* stat_fns.h: written -- has some simple file testing routines
+
+	* mystring: added a 'length' member to the class to allow for
+	faster length calculations
+
+	* checkvpw.texi: updated the documentation for vdeluser
+
+	* spec: added vdeluser to list of programs
+
+	* vdeluser.cc: re-write vdeluser perl script as C++ to avoid any
+	dependancies on perl
+
+	* passwdfn.cc (fdelpwnam): wrote function to delete an entry
+
+	* checkvpw.cc (auth_virtual): use definition instead of "passwd"
+
+	* config.h: added definition for the temporary password file
+
+	* vadduser.cc (main): moved setting the password back up before
+	creating any of the rest of the account -- if a user mis-types a
+	password, none of the rest of the account will be created
+	accidentally.
+
+Wed Sep 17 10:02:58 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* vdeluser: wrote (as a perl script) to delete mail users
+
+	* released version 0.55-1
+
+	* checkvpw.texi: updated the documentation
+
+	* released version 0.54-2
+
+	* spec: added a %attr tag for the documentation files.
+
+Tue Sep 16 10:50:16 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.54-1
+
+	* checkvpw.cc (auth_virtual): make the maildir string point to a
+	subdirectory in USER_DIR
+
+	* vadduser.cc: user mail directories are now stored in USER_DIR
+
+	* config.h: created for global defines
+
+	* mystring.cc (subst): substitute all instances of the <from>
+	character with the <to> character (new)
+
+	* vadduser.cc (main): create symlinks to the master .qmail-<user>
+	file instead of creating multiple files for aliases
+
+	* released version 0.53-1
+
+	* passwdfn.cc (fsetpwnam): fixed a bug that prevented more than
+	one entry from being added to a password file
+
+	* vadduser.cc (main): changed the default UID and GID to add to
+	the password file to the current UID and GID
+
+Mon Sep 15 16:55:09 1997  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* released version 0.52-2
+
+	* modified file structure to move sources and documentation into
+	separate directories
+
+	* released version 0.52-1
+
+	* Changed program name to checkvpw.  I never did like the long
+	name...
+
+	* Added GNU COPYING file to package.
+	
+	* vadduser.cc (make_dot_qmail): checks for the .qmail-<ext> file
+	before creating one
+	(main): checks for the user in the password file before adding one
+
+	* passwdfn.cc (fsetpwnam): modified to create the file if it
+	doesn't exist
+
+	* released version 0.51-2
+
+	* added ChangeLog and TODO to spec file
+
+	* vpasswd.cc (main): vpasswd no longer requires that the
+	administrator types in the old password to change to a new one
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/ChangeLog.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,3768 @@
+<html>
+<head><title>ChangeLog</title></head>
+<body>
+<p>2000-09-30  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>Released version 0.96.9
+
+<li>python/commands.py (adduser): Fixed a typo that prevents users
+without a mailbox from being added.
+
+</ul>
+</p>
+<p>2000-09-15  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>authenticate/authvlib.cc (check): Always set VUSER, even if
+virtname is blank.
+
+</ul>
+</p>
+<p>2000-09-14  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>daemon/main.cc: Exit immediately if a SIGPIPE or SIGALRM is
+caught.
+
+</ul>
+</p>
+<p>2000-09-12  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>pyadmin/vmailmgr_lib.py (Flag.html): Added this method to print
+out a HTML select list with the correct item selected.
+
+<li>pyadmin/vmailmgr_sessiond.py: New program set up to track
+session status in memory instead of on disk.
+
+<li>pyadmin/vmailmgr_pyadmin.py (cgi_main): Create a Context object
+for passing in to format_page.
+
+<li>pyadmin/vmailmgr_parser.py (Context): Defined this context
+object that wraps context data.  This will be extended to stack
+contexts.  When doing a __getitem__, if the key is not found in
+the context dictionary, that key is evaluated as an expression
+with the dictionary as local variables.
+(Foreach.do_end): Pass the formatted sections to
+stack.append_or_print instead of printing them directly.
+
+</ul>
+</p>
+<p>2000-09-11  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>Removed all old Python support code, replace by the new
+"pyadmin" interface.
+
+</ul>
+</p>
+<p>2000-09-05  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>daemon/dispatch.cc (dispatch_cmd): Don't add "-virtuser" to
+baseuser name if virtuser is empty.
+
+</ul>
+</p>
+<p>2000-09-04  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>python/vmailmgr_cgi.py.in (Session): Added prototype for new
+class to manage session data.
+
+<li>daemon/check.cc (CMD): Simplified the logic, elimited the return
+value.  Now returns either error or OK.
+
+</ul>
+</p>
+<p>2000-09-01  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>doc/FAQ.sgml: Added section on long POP3 logins.
+
+</ul>
+</p>
+<p>2000-08-22  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>commands/vdeliver.cc (deliver_partial): Fail permanently if: the
+open failed, EDQUOT is defined, and the error number is EDQUOT.
+
+</ul>
+</p>
+<p>2000-08-15  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>daemon/deluser.cc (CMD): Use new form of vdomain::deluser.
+
+<li>lib/vpwtable/reader.cc (vpwtable_reader): Removed the call to
+end here, which produced a missing reference to
+vpwtable_reader::end.
+
+</ul>
+</p>
+<p>2000-08-13  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>commands/*.cc: Moved all the POD man page documentation into the
+source files using a new CLI documentation generator.
+
+</ul>
+</p>
+<p>2000-08-11  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>commands/vdeluser.cc: Added an option to prevent vdeluser from
+deleting a user with a mailbox.
+
+<li>lib/vdomain/deluser.cc (deluser): Added a flag to make deluser
+not delete users with a mailbox.
+
+<li>daemon/main.cc: Fixed up some of the cli_* values.
+
+<li>doc/FAQ.sgml: Added note regarding difference between vmailmgr
+and vpopmail.
+
+<li>lib/vpwtable/gdbm_read.cc (class gdbm_vpwtable_reader): Added
+this new subclass of vpwtable_reader.
+
+<li>lib/vpwtable/cdb_read.cc (class cdb_vpwtable_reader): Added this
+new subclass of vpwtable_reader.
+
+<li>lib/vpwtable/vpwtable.h (class vpwtable_reader): Removed the
+short-sighted conditional mess in this class with virtual methods.
+
+</ul>
+</p>
+<p>2000-08-10  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>Released version 0.96.8
+
+<li>authenticate/authvlib.cc (set_user): Call pwentry::export_env
+instead of doing it manually.
+
+<li>lib/misc/pwentry_export_env.cc (export_env): Added this routine
+to export USER and HOME for a real user.
+
+<li>commands/vcheckquota.cc (link_softquota_message): Fixed bug in
+multiple use of atoi.
+
+<li>doc/HOWTO.sgml: Added a note on vsetup.
+
+</ul>
+</p>
+<p>2000-08-04  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>doc/FAQ.sgml: Added notes on location of qmail-autoresponder and
+the CVS repository.
+
+<li>daemon/autoresponse.cc (autoresponse_read): If the normal
+autoresponse file can't be read, try the disabled file.
+(autoresponse_status): Added status command.
+
+<li>commands/vcheckquota.cc (link_softquota_message): Added code to
+symlink in warning message if softquota fails.  This will link the
+message in each time soft quota fails.
+
+</ul>
+</p>
+<p>2000-08-03  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>commands/vdeliver.cc (cli_main): Make sure to rewind stdin
+before executing vdeliver-postdeliver.
+
+<li>daemon/lookup.cc: Rewritten to output the entire virtual user
+data instead of just the mailbox and aliases.
+
+<li>commands/vcheckquota.cc: Changed many instances of "int" to
+"unsigned".
+(check_quota): Always check incoming message size, and check max
+count even if no quotas apply.
+
+<li>lib/misc/exec.cc (execute_one): Fixed a bug where this would
+return the raw status value instead of WEXITSTATUS(status).
+
+</ul>
+</p>
+<p>2000-08-02  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>daemon/autoresponse.cc (autoresponse_write): Applied bugfix that
+would allow disabled autoresponses to be written.
+
+</ul>
+</p>
+<p>2000-08-01  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>commands/vcheckquota.cc (exit_msg): Fixed typo (used to say
+"vdeliver:").
+(cli_main): Fixed another typo -- VUSER_MAILDIR is not set, plain
+MAILDIR is.
+
+<li>authenticate/checkvpw.cc (main): Removed call to execute
+checkvpw-postsetuid.
+
+<li>authenticate/authvlib.cc (set_user): Added a hook to execute the
+proper presetuid script.
+(authenticate): Added a hook to execute the proper postsetuid
+script.
+
+</ul>
+</p>
+<p>2000-07-31  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>daemon/lookup.cc (lookup_and_validate): Set the "nodefault" flag
+in vdomain::lookup to true instead of false -- it's never correct
+to look up the default user in the daemon.
+
+</ul>
+</p>
+<p>2000-07-18  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>commands/vcheckquota.cc: Added this new program, originally
+authored by Eugene Miretskiy, and subsequently modified.
+
+</ul>
+</p>
+<p>2000-07-17  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>doc/HOWTO.sgml, doc/FAQ.sgml: Updated documentation.
+
+</ul>
+</p>
+<p>2000-07-05  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>Released version 0.96.7.
+
+<li>lib/vpwtable/cdb_read.cc: Added CDB support for the vpwtable
+reader class.
+
+<li>daemon/listdomain.cc (CMD_FD): Adjusted to use the new vpwtable
+reader.
+
+<li>commands/listvdomain.cc (cli_main): Adjusted to use new vpwtable
+reader.
+
+<li>lib/vpwtable/gdbm_read.cc (vpwtable_reader): Added this new
+class to replace the stream reading support from the vpwtable
+class.
+
+</ul>
+</p>
+<p>2000-07-04  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>lib/vpwtable/gdbm_getbyname.cc (getbyname): Lowercase the name
+before retrieving it.
+
+<li>commands/listvdomain.cc (cli_main): Exit with error if listing
+an individual user fails.
+
+<li>lib/vpwtable/gdbm_get.cc (start): Fixed missing gdbm_firstkey.
+
+<li>commands/vpasswd2db.cc: Added new utility to convert plain text
+password tables into whatever vpwtable format was configured.
+
+</ul>
+</p>
+<p>2000-06-25  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>python/vmailmgr.py.in: Added deluser and chattr commands.
+
+</ul>
+</p>
+<p>2000-06-24  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>doc/configuration.texi (socket-file): Reinstated this config
+section.
+
+<li>daemon/autoresponse.cc (autoresponse_delete): Added a new
+command to delete the autoresponse data.
+
+<li>lib/misc/maildir.cc (delete_directory): Renamed from
+delete_maildir.
+
+<li>daemon/autoresponse.cc (autoresponse_write): Create the
+autoresponse directory if it does not already exist.
+
+</ul>
+</p>
+<p>2000-06-19  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>lib/vpwtable: Added GDBM support in the gdbm_*.cc files.
+
+<li>lib/vpwtable/cdb_vpwtable.cc: Made the ".cdb" string a constant.
+
+<li>lib/vpwtable: Renamed all the .cc files to "cdb_*.cc".
+
+</ul>
+</p>
+<p>2000-06-14  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>doc/configuration.texi: Added notes on the autoresponse
+configuration items, removed the notes on max-fork and
+socket-file.
+
+</ul>
+</p>
+<p>2000-06-13  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>daemon/main.cc (cli_main): Rewrote main to use the cli library.
+This removes extra command line parsing code and incidentally
+fixes a problem with random not being initialized.
+
+<li>daemon/log.cc (log): Revised handling of printing PIDs.
+
+<li>daemon/dispatch.cc: Removed "forkstat" command.
+
+<li>daemon/main.cc: Removed support code needed to create and accept
+connections on a UNIX domain socket, in favour of using the new
+ucspi-unix package.
+
+</ul>
+</p>
+<p>2000-06-01  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>Released version 0.96.6
+
+<li>commands/vdeliver.cc (cli_main): Fixed typo in order of
+operands in call to exit_msg.
+
+<li>lib/misc/map_table.cc (map_table): Lower case all keys to allow
+for case insensitive comparisons.
+
+<li>lib/misc/lookup_domain.cc (find_virtual): Fixed bug: domain
+names are not case sensitive.
+
+</ul>
+</p>
+<p>2000-05-31  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>python/vmailmgr.py.in (VUser.from_binary): Fixed some bugs in
+the conversion of flags.
+
+</ul>
+</p>
+<p>2000-05-25  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>python/vmailmgr_cgi.py.in (print_html): Added code to print out
+a HTML error if the requested file could not be printed.
+(wrap_print): Print out basename+"-success" on success, and
+provide a default error response if the error file does not
+exist.
+
+<li>daemon/daemon.h (CMD): Removed a bogus "const" from the
+declarations of the CMD and CMD_FD macros.
+
+<li>daemon/autoresponse.cc (CMD_FD): Added proper command logging to
+this command.
+(CMD_FD): Fixed type -- a virtual user's password is acceptable.
+
+<li>daemon/log.cc: Added a new LOG_MESSAGE constant.
+
+<li>doc/FAQ.sgml: Added a brief section on how to configure
+qmail+patches for use with vmailmgr.
+
+<li>doc/configuration.texi (qmail-root): Added this missing section.
+
+</ul>
+</p>
+<p>2000-05-24  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>python/vmailmgr_cgi.py.in (cgi_main): Trap trying to run the
+program outside of a CGI environment.
+
+<li>python/vmailmgr.py.in (VUser): Added this class to represent the
+data associated with a virtual user.  A special __getitem__
+routine allows the data to be read as a dictionary.
+(Daemon): More code reorganization in this class.
+(listdomain): Added this command, which returns a dictionary of
+all the users in the domain.
+(adduser): Added this command to add a virtual user.
+(autoresponse): Added this command, which executes the daemon
+"autoresponse" command.
+
+<li>python/vmailmgr_cgi.py.in (wrap_print): Added this new routine,
+which wraps a call to a vmailmgr command in a try/except block,
+and prints an output file based on the results.
+
+<li>Added SGML documentation from Dan Kuykendall.
+
+</ul>
+</p>
+<p>2000-05-16  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>python/vmailmgr_cgi.py.in: Moved all the CGI specific
+functionality into this new module.
+
+<li>python/vmailmgr.py.in: Removed the "Response" class and turned
+error responses into exceptions.  The server socket is not closed
+at the end of a command to allow a listdomain command to read more
+data after the initial response.
+
+</ul>
+</p>
+<p>2000-05-09  Bruce Guenter  &lt;bruce@bruce-guenter.dyndns.org&gt;
+<ul>
+
+<li>commands/vdeliver.cc (cli_main): Error exits from executing
+"vdeliver-predeliver" would unconditionally result in a temporary
+failure for qmail.  Fixed to return the actual error number to
+qmail.
+
+</ul>
+</p>
+<p>2000-05-02  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>cgi/vchforwards.cc (CGI_MAIN ): Fixed an internal glitch -- the
+new "do_enable" and "do_disable" internal variables were
+duplicated.
+
+<li>daemon/lookup.cc (lookup_and_validate): Modified to use the new
+set_defaults method.
+
+<li>commands/vchattr.cc: Make size limits refer to bytes.
+
+<li>doc/configuration.texi: Indicate that size limits are in units
+of bytes.
+
+<li>commands/vadduser.cc: Make size limits refer to bytes
+everywhere.
+
+<li>commands/vsetup.cc (setup_alias): Modified to use the new
+set_defaults method.
+
+<li>commands/vpasswd2cdb.cc (getpw): Removed set_defaults call,
+since from_record calls set_defaults after doing conversion from
+the old format data.
+
+<li>commands/vaddusers.cc (add_one): Modified to use the new
+set_defaults method.
+
+<li>lib/vpwentry/from_old.cc (from_old_record): Modified to use the
+new set_defaults method.
+
+<li>commands/vadduser.cc: Modified to use the new set_defaults
+method.
+
+<li>lib/vpwentry/defaults.cc (set_defaults): Add a flag to set the
+creation time to either now (true) or 0 (false -- for old
+records), as well as a flag to set the boolean flags.
+
+<li>lib/misc/strtou.c: Use UINT_MAX instead of (unsigned)-1.
+
+<li>lib/config/showvconfig.cc.in: Use UINT_MAX instead of
+(unsigned)-1.
+
+<li>lib/config/configrc.in: Use UINT_MAX instead of (unsigned)-1.
+
+<li>lib/misc/lookup_domain.cc (find_virtual): Use UINT_MAX instead
+of (unsigned)-1.
+
+<li>lib/vpwentry/defaults.cc (set_defaults): Use UINT_MAX instead of
+(unsigned)-1.
+
+<li>lib/misc/utoa.cc (utoa): Use UINT_MAX instead of (unsigned)-1.
+
+<li>lib/vpwentry/from_ver1.cc (from_ver1_record): Set the flags
+before returning.
+
+<li>lib/vpwentry/from_old.cc (from_old_record): Set the flags before
+returning.
+
+</ul>
+</p>
+<p>2000-04-19  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>doc/vchattr.pod: Added note regarding personal information.
+
+<li>doc/vmailmgr-cgi.texi (Top): Added note regarding personal
+information.
+
+<li>commands/vchattr.cc: Allow changing the personal information.
+
+<li>lib/vdomain/chattr.cc (chattr): Added code to handle changing
+the personal information.
+
+</ul>
+</p>
+<p>2000-04-18  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>doc/FAQ.texi (Does vmailmgr support IMAP?): Updated to describe
+current status of IMAP support.
+
+<li>daemon/dispatch.cc: Added autoresponse dispatch entry.
+
+<li>daemon/autoresponse.cc: Added autoresponse command from Mike Bell.
+
+</ul>
+</p>
+<p>2000-04-14  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>Modified the spec file to put the Courier IMAP module into a
+seperate package.
+
+<li>Copied the necessary sources from Courier IMAP to build a
+minimal stand-alone libauthmod in order to build the
+authentication module without needing the Courier IMAP sources.
+
+</ul>
+</p>
+<p>2000-04-13  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>Released version 0.96.5
+
+<li>doc/vchattr.pod: Wrote a man page for the vchattr command.
+
+</ul>
+</p>
+<p>2000-04-12  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>commands/vdeliver.cc (cli_main): Check if the account has
+expired before delivering.
+
+<li>authenticate/authvlib.cc (check): Check if the acount has
+expired and fail if so.
+
+<li>lib/vpwentry/export_env.cc (export_env): Set
+"VUSER_MAILBOX_ENABLED" to the new flag.
+
+<li>authenticate/authvlib.cc (check): If looking up the base user
+fails, and virtual_only is set, return instead of failing hard.
+
+<li>daemon/chattr.cc (CMD): Allow mailbox enabled flag to be changed
+by virtual users.
+
+<li>commands/listvdomain.cc (show_user): Print out "(disabled)" next
+to the mailbox directory if the "is_mailbox_enabled" flag is not
+set.
+
+<li>cgi/listvdomain.cc (show_user): Adapted to using
+vpwentry::from_record instead of vpwentry::from_ver1_record.
+
+<li>lib/vpwentry/vpwentry.cc: Set the flag defaults here on creation
+instead of in set_defaults.
+
+<li>lib/vdomain/chattr.cc (chattr): Modified to use the new vpwentry
+is_mailbox_enabled flag.
+
+<li>lib/vpwentry/from_ver1.cc (from_ver1_record): Made this a
+protected non-static method.
+
+<li>lib/vpwentry/from_ver2.cc (from_ver2_record): Made this a
+protected non-static method.
+
+<li>lib/vpwentry/from_old.cc (from_old_record): Made this a
+protected non-static method.
+
+<li>lib/vpwentry/from.cc (from_record): Made this a non-static method.
+
+<li>lib/vpwentry/decode.cc: Moved the common pieces from from_ver1
+and from_ver2 into seperate routines and moved them here.
+
+<li>lib/vpwentry/from_ver2.cc (from_ver2_record): Added this routine
+to do conversions from the new binary record format.
+
+<li>lib/vpwentry/to.cc (to_record): Modified to create the new
+binary record format.
+
+<li>lib/vpwentry/from_uint.cc (from_uint): Moved this routine out of
+from_ver1.cc, as it's common to both ver1 and ver2 (and other)
+records.
+
+<li>lib/vdomain/chattr.cc: Returned the extraneous definition of
+strtou from here.
+
+<li>lib/config/read_uns.cc (read_uns): Coded to use our strtou.
+
+<li>lib/misc/strtou.c (strtou): Renamed the C++ source to a C
+source, and added a header file.  Added a null-pointer and leading
+space check.
+
+<li>lib/vpwentry/vpwentry.h (struct vpwentry ): Removed the
+enable/disable routines and added a "is_mailbox_enabled" boolean
+flag.
+
+</ul>
+</p>
+<p>2000-04-11  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>cgi/vadduser.cc (CGI_MAIN ): Added code to handle adding
+forwarding at the same time as the user.
+
+<li>lib/misc/lookup_baseuser.cc (lookup_baseuser): Modified to use
+mystring::left instead of a hacked-up constructor call.
+
+<li>cgi/vchforwards.cc (CGI_MAIN ): Added code here to handle
+enabling and disabling the mailbox.
+
+<li>commands/vchattr.cc: Added handling in this code for the new
+flag.
+
+<li>lib/vdomain/chattr.cc (chenabled): Added this function to enable
+or disable delivery to a virtual user.
+
+<li>lib/vpwentry/is_enabled.cc (is_enabled): Modified this routine
+to return false if no mailbox path is set.
+
+<li>commands/vdeliver.cc (cli_main): Handle the "enabled" flag here
+by not doing mailbox delivery if is_enabled returns false.
+
+<li>lib/vpwentry/is_enabled.cc (is_enabled): Created this routine to
+determine if the account has been disabled.
+
+<li>lib/vpwentry/disable.cc: Created routines here to enable and
+disable an account by removing and creating a "disabled" file in
+the virtual user's mailbox directory.
+
+<li>Released version 0.96.4
+
+<li>lib/misc/exec.cc (presetenv): Changed this routine to allocate a
+new string (char*) that it never frees.  This seems to fix the
+problems with garbage making its way into the environment.
+
+</ul>
+</p>
+<p>2000-04-10  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>lib/vpwentry/export_env.cc (export_env): Moved the setenv
+routine that exported a vpwentry to this method of vpwentry.
+
+<li>lib/misc/exec.cc (presetenv): Renamed "setenv" to this, to
+prevent confusion with any built-in "setenv" functions.
+
+<li>authenticate/authvmailmgr.cc: Made the user name, pass phrase,
+and domain name into globals, to prevent their memory from being
+deallocated prematurely.
+
+</ul>
+</p>
+<p>2000-04-09  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>doc/vmailmgr-cgi.texi: Adjusted this documentation to fit the
+new CGIs.
+
+<li>cgi/vaddalias.cc (CGI_MAIN ): Modified to handle a
+comma-seperated list of destinations.
+
+<li>cgi/vchforwards.cc: Renamed vchalias to this file, to match the
+command-line program's name change.
+(CGI_MAIN ): Modified to handle a comma-seperated list of destinations.
+
+</ul>
+</p>
+<p>2000-04-07  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>Updates for new mystring and fdbuf libraries.
+
+<li>commands/vsetup.cc: Added a "quiet" flag.
+
+<li>commands/vpopbull.cc: Added a "quiet" flag.
+
+<li>commands/vpasswds.cc: Added a "quiet" flag.
+
+<li>commands/vpasswd2cdb.cc: Added a "quiet" flag.
+
+<li>commands/vpasswd.cc: Added a "quiet" flag.
+
+<li>commands/vdeluser.cc: Added a "quiet" flag.
+
+<li>commands/vaddusers.cc: Added a "quiet" flag.
+
+<li>commands/vdeliver.cc: Added a "quiet" flag.
+
+<li>commands/vchforwards.cc: Added a "quiet" flag.
+
+<li>commands/vchattr.cc: Added a "quiet" flag.
+
+<li>commands/listvdomain.cc: Added a "quiet" flag.
+
+<li>commands/vadduser.cc: Added a "quiet" flag.
+
+<li>authenticate/authvlib.cc (check): make the virtual / non-virtual
+decision here rather than in authenticate, in order to handle
+"baseuser-virtuser" type usernames.  This fixes the Courier-IMAP
+auth module problems.
+
+</ul>
+</p>
+<p>2000-04-06  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>doc/FAQ.texi (Upgrading from Previous Versions): Added this
+section to answer questions regarding what needs to be done to
+upgrade to the current version.
+
+</ul>
+</p>
+<p>2000-04-05  Bruce Guenter  &lt;bguenter@daedalus.bfsmedia.com&gt;
+<ul>
+
+<li>Released version 0.96.3
+
+</ul>
+</p>
+<p>2000-04-04  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>doc/vmailmgr-cgi.texi (Top): Expanded the "vadduser" section to
+explain the new optional "userdir" field.
+
+<li>cgi/vadduser.cc (CGI_MAIN ): Modified to use the new adduser2
+interface.
+
+<li>cgi/vaddalias.cc (CGI_MAIN ): Modified to use the new adduser2
+interface.
+
+<li>daemon/dispatch.cc: Removed dispatch entries for adduser,
+addalias, and addaliasp.
+
+<li>daemon/adduser2.cc (CMD): Added this new command, which combines
+the functionality of adduser, addalias, and addaliasp.
+
+<li>daemon/addaliasp.cc (CMD): Modified to use build_forwards.
+
+<li>daemon/addalias.cc (CMD): Modified to use build_forwards.
+
+<li>daemon/adduser.cc (CMD): Only add non-empty forwarding addresses.
+(build_forwards): Moved the forward-list building code common to
+adduser, addalias, and addaliasp into this routine.
+
+<li>daemon/main.cc (handle_connection): Log command response before
+attempting to send data back to client.
+(abortreq): Log abort code before closing FD.
+(decode_data): Removed the test to check for empty parameters,
+since some of the modules expect this possibility.
+
+</ul>
+</p>
+<p>2000-04-03  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>authenticate/vauthenticate.cc (getdata): Buffer doesn't need to
+be static.
+
+<li>authenticate/checkvpw.cc (getdata): buffer doesn't need to be
+static.
+
+<li>lib/vpw/vpwtable.h (class vpwtable): Moved the vpwtable class
+definition into this file.
+
+</ul>
+</p>
+<p>2000-04-01  Bruce Guenter  &lt;bruceg@daedalus.bfsmedia.com&gt;
+<ul>
+
+<li>Released version 0.96.2
+
+<li>daemon/state.cc: Since the daemon always forks, remove all of
+the uid/gid saved state, and never restore it.  This class should
+be renamed, since it does not really "save" any significant state.
+
+<li>commands/vaddalias: Fixed quoting bug in this script.
+
+</ul>
+</p>
+<p>2000-03-21  Bruce Guenter  &lt;bruceg@daedalus.bfsmedia.com&gt;
+<ul>
+
+<li>authenticate/vauthenticate.cc (main): Authenticate as virtual
+only, and print out the user data if authentication succeeds.
+
+<li>authenticate/authvlib.cc (authenticate): Fixed typo declaring
+"baseuser" twice, preventing authentication from working.
+
+</ul>
+</p>
+<p>2000-03-07  Bruce Guenter  &lt;bruceg@daedalus.bfsmedia.com&gt;
+<ul>
+
+<li>authenticate/vauthenticate.cc: Added this simple module that
+accepts domain name, user name, and pass phrase on stdin, and
+exits successfully if they can be authenticated.
+
+</ul>
+</p>
+<p>2000-02-12  Bruce Guenter  &lt;bruceg@daedalus.bfsmedia.com&gt;
+<ul>
+
+<li>commands/vaddalias: Made this mini-program into a shell script.
+
+<li>daemon/chattr.cc (CMD): Translate multiple values into a single
+NUL-delimited list.
+
+<li>commands/vsetup.cc (cli_main): Added error messages if execution
+of vsetup-pre or vsetup-post fails.
+
+<li>Removed old php3 support and placed Mike Bell's PHP3 code in.
+
+<li>Applied patches by Mike Bell to allow vsetup to run a command
+before and after executing.
+
+</ul>
+</p>
+<p>2000-02-03  Bruce Guenter  &lt;bruceg@daedalus.bfsmedia.com&gt;
+<ul>
+
+<li>doc/FAQ.texi: Fixed typo reversing virtuser and baseuser.
+
+</ul>
+</p>
+<p>2000-01-12  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>authenticate/authvmailmgr.cc: Completed initial coding of this
+module, still needs testing.
+
+<li>authenticate/checkvpw.cc (fail): Removed unused string "r".
+
+</ul>
+</p>
+<p>2000-01-05  Bruce Guenter  &lt;bguenter@bguenter.pointsnorth.com&gt;
+<ul>
+
+<li>authenticate/authvmailmgr.cc: Started authentication module for
+Courier IMAP.
+
+<li>authenticate/authvlib.cc: Moved some of the functions out of
+checkvpw.cc and generalized them here.
+
+<li>authenticate: Moved checkvpw directory here.
+
+</ul>
+</p>
+<p>1999-10-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>checkvpw/checkvpw.cc (authenticate): Changed logic here to
+assume a missing entry in both locals and virtualdomains is
+intended to be local.
+
+</ul>
+</p>
+<p>1999-10-08  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/*.cc: Modified to use new validate_forward.
+
+<li>lib/misc/vdomain_chattr.cc (chdest): Modified to use new
+validate_forward.
+
+<li>lib/misc/vdomain_validate.cc (validate_forward): Renamed
+validate_redirect to this, and removed the handling for a
+comma-seperated list of addresses.
+
+<li>commands/vchforwards.cc (cli_main): Added code to validate the
+forwarding addresses.
+
+<li>commands/vadduser.cc (make_user): Validate the forwarding
+addresses before creating the user.
+
+</ul>
+</p>
+<p>1999-10-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/chattr.cc (CMD): Changed call to strtol to strtoul.
+
+<li>lib/config/read_uns.cc (read_uns): Modified this routine to
+treat all negative numbers as -1, and changed the call from strtol
+to strtoul.
+
+</ul>
+</p>
+<p>1999-10-04  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/FAQ.texi: Updated the answers and added information about
+how mail gets delivered.
+
+<li>lib/misc/vdomain_add.cc: Removed both vdomain::addalias and
+vdomain::adduser.
+
+<li>commands/vsetup.cc (setup_alias): Removed the use of
+vdomain::addalias.
+
+<li>commands/vadduser.cc (add_alias): Removed the use of
+vdomain::addalias.
+
+<li>commands/vaddusers.cc (add_one): Removed the use of
+vdomain::adduser and vdomain::addalias.
+
+</ul>
+</p>
+<p>1999-10-03  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.96.1
+
+<li>doc/vmailmgr-cgi.texi: Updated listvdomain documentation.
+
+<li>cgi/listvdomain.cc (show_user): Merged show_mbox and show_alias
+into this one routine.
+(load_users): Fixed length of incoming code.
+(show_user): Changed formatting of aliases.
+
+</ul>
+</p>
+<p>1999-10-01  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/listvdomain.cc: Recoded to use modified listdomain protocol
+interface.
+
+<li>lib/misc/vdomain_add.cc (addalias, adduser): Call set_defaults
+on new vpwentry.
+
+<li>lib/misc/vpwentry_from_old.cc (from_old_record): Call
+set_defaults on resulting vpwentry.
+
+<li>commands/vadduser.cc (make_user): Call set_defaults on new
+vpwentry.
+
+<li>daemon/lookup.cc (lookup_and_validate): Call set_defaults on new
+vpwentry.
+
+<li>lib/misc/vpwentry.cc: Moved vpwentry::set_defaults into its own
+module, and removed the call to set_defaults from the constructors.
+
+<li>lib/misc/vpwentry_from.cc: Made the from_old_record and
+from_ver1_record public, and moved them into their own modules.
+
+<li>daemon/listdomain.cc (CMD_FD): Changed the protocol to strip the
+count from the initial message, to output each entry as a seperate
+response (with length and all), and to include full vpwentry
+details in each entry rather than requiring seperate lookups.
+
+</ul>
+</p>
+<p>1999-09-30  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.96
+
+<li>checkvpw/checkvpw.cc (main): Removed extraneous ; causing bug.
+
+<li>lib/misc/exec.cc (execute): Skip over directories with identical
+parents, to prevent double execution.
+
+<li>checkvpw/checkvpw.cc (check): Fixed inverted "nodefault" flag to
+domain-&gt;lookup.
+
+<li>lib/misc/vpwentry_from.cc (from_record): Turned the if/else
+block into a switch statement.
+
+<li>commands/vadduser.cc (set_defaults): Turn off creation of a
+mailbox if the base command name is "vaddalias".
+Also, use argv0base instead of "vadduser" for the command name.
+
+<li>lib/misc/vpwentry_from.cc (from_ver1_record): Fixed bug in
+importing version 1 records.
+
+<li>commands/vdeliver.cc (dump): The input needs to be rewound here
+the second time through, so rewind it always.
+
+</ul>
+</p>
+<p>1999-09-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/listvdomain.cc (cli_main): Print out a banner before
+the listing.
+
+</ul>
+</p>
+<p>1999-09-27  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/configuration.texi: Updated the configuration documentation
+to match current implementation aspects.
+
+<li>lib/misc/exec.cc (execute): Changed behavior of execute to
+execute the global before the local directories, and to abort on
+any error, but translate 99 to 0 (no error).
+
+</ul>
+</p>
+<p>1999-09-23  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/vaddalias.cc (CGI_MAIN ): Adjusted for changed parameter
+ordering.
+
+<li>daemon/log.cc: Added several password-obscuring constants,
+rather than repeating them in each command.
+
+<li>daemon/lookup.cc (CMD): Changed format of result.
+
+<li>daemon/check.cc (CMD): Changed format of result to seperate
+parts with a NUL.
+
+<li>daemon/addalias.cc (CMD): Now takes multiple destinations.
+
+<li>daemon/addaliasp.cc (CMD): Changed order of parameters to allow
+for multiple destination parameters.
+
+<li>daemon/log.cc (logcommand): Removed all varieties of this
+function except the one that takes a single "command" argument.
+
+<li>daemon/adduser.cc (CMD): Added handling for a list of forwards.
+
+<li>daemon/dispatch.cc (dispatch_cmd): Changed handling of commands:
+there is now a minimum and a maximum number of arguments, and the
+"decode_virtual" is a manditory -- if set, the "baseuser-virtual"
+format is not allowed.  This means all the server commands now
+require seperate domain name and virtual user name arguments (all
+the CGIs do this anyways).
+
+<li>daemon/check.cc (CMD): Added handling for mailbox and multiple
+forwards of virtual users.
+
+<li>daemon/dispatch.cc: Added check back into the list of commands.
+
+<li>cgi/vcommand.py (main): Adapted to new interface.
+
+<li>cgi/vmailmgr.py: Revised the interface to be somewhat more
+object based, and tested minimally.
+
+</ul>
+</p>
+<p>1999-09-22  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/listvdomain.cc (setup_format): Added handling for cell and
+title prefix and suffix strings, as well as cell, paragraph, and
+table alignment.
+
+</ul>
+</p>
+<p>1999-09-20  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/vmailmgr.py: Split off most of the generic functionality
+from vcommand.py into this module, completed base CGI
+functionality.
+
+</ul>
+</p>
+<p>1999-09-19  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/vcommand.py: Started this generic Python vmailmgr command
+CGI.
+
+</ul>
+</p>
+<p>1999-09-16  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vdeliver.cc (cli_main): Adapted to the new execution
+framework.
+
+<li>checkvpw/checkvpw.cc (check): Adapted to the new execution
+framework.
+
+<li>lib/misc/exec.cc (execute): Removed the old "exec" framework in
+favour of this function, which traverses through the configuration
+directories and tries to execute the named file.
+
+<li>doc/vadduser.pod: Updated this documentation.
+
+<li>commands/vadduser.cc: Added an option to not create a mailbox
+for this user, allowing this program to be used in place of
+vaddalias.
+(add_user): Modified logic to optionally ask for a password.
+
+<li>commands/vconf2dir: Fixed quoting when creating the new config
+files, and removed the "set -x" flag at the top.
+
+<li>commands/vchforwards.cc (cli_main): Adapted this program from
+vchalias, and removed vchalias from the distribution.
+
+<li>commands/vchattr.cc: Wrote this command to change a virtual
+user or users' attributes.
+
+</ul>
+</p>
+<p>1999-09-15  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>checkvpw/checkvpw.cc: Login failures cause execution of
+"config/checkvpw-loginfail", and other failures cause execution of
+"config/checkvpw-error", both with an error message in
+$CHECKVPW_ERROR.
+
+<li>commands/vdeliver.cc (deliver_partial): Rewrote loop so that
+looping will always sleep.  If the file creation failed, it would
+previously loop immediately.
+
+</ul>
+</p>
+<p>1999-09-14  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/FAQ.texi: Replaced references to vmailmgr.conf with
+vmailmgr/
+
+</ul>
+</p>
+<p>1999-09-11  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/vpopbull.pod: Wrote a man page for vpopbull.
+
+</ul>
+</p>
+<p>1999-09-10  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vpwentry_auth.cc (authenticate): Wrote this new
+routine, to replace the use of crypt_cmp when authenticating
+virtual users.
+
+<li>lib/misc/pwentry_auth.cc (authenticate): Wrote this new routine,
+to replace the use of crypt_cmp when authenticating users.
+
+</ul>
+</p>
+<p>1999-09-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/listvdomain.cc: Added options to list only users, only
+aliases, or selected names listed on the command line.
+
+<li>lib/misc/vpwentry_from.cc (from_ver1_record): Fixed off-by-one
+bug.
+
+<li>lib/misc/vpwentry_to.cc (to_record): Fixed problem in creating
+records without any forwarding addresses.
+
+<li>commands/vadduser.cc: Commented out extra-data handling.
+
+<li>lib/misc/exec.cc (setenv): Commented out
+
+<li>lib/misc/vpwentry.h (struct vpwentry ): Commented out the extra
+data string.
+
+<li>cgi/vchattr.cc (CGI_MAIN ): Wrote this simple modification to
+vchalias, which can change any attribute.
+
+<li>daemon/chattr.cc (CMD): Convert the attr string to an integer
+before running domain.chattr.
+
+<li>lib/misc/vdomain_chattr.cc (chattr): Added attribute handlers
+for message size/count and account expiry.
+
+<li>lib/misc/vdomain.h (class vdomain): Changed attribute name
+constants from strings to integers.
+
+</ul>
+</p>
+<p>1999-08-23  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/configuration.texi (Search Order): Corrected a typo: the
+local directory is named ".vmailmgr", not "vmailmgr".
+
+</ul>
+</p>
+<p>1999-08-21  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vadduser.cc: Added hard/soft quota options, and a
+password option for vaddalias.
+
+<li>lib/misc/vpwentry.h (struct vpwentry ): Added hard/soft quota
+values.
+
+</ul>
+</p>
+<p>1999-08-18  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vpasswd.cc (cli_main): Modified to call
+vdomain::chattr.
+
+<li>commands/vpasswds.cc (change_one): Modified to call
+vdomain::chattr.
+
+<li>cgi/vchalias.cc (CGI_MAIN ): Use ATTR_DEST instead of a
+hard-coded string.
+
+<li>cgi/vpasswd.cc (CGI_MAIN ): Use ATTR_PASS instead of a
+hard-coded string.
+
+<li>daemon/chattr.cc (CMD): Modified to call vdomain::chattr.
+
+</ul>
+</p>
+<p>1999-08-16  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vdomain_chattr.cc (chattr): Created this new routine to
+generalize attribute modification.
+
+</ul>
+</p>
+<p>1999-08-15  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/exec.cc (exec_list): Takes a strlist parameter instead
+of a string.
+
+<li>lib/misc/strlist.h (class strlist ): Removed the NUL constant.
+
+<li>lib/misc/vpwentry.h (struct vpwentry ): Removed the NUL constant
+in favour of the new one in mystring.
+
+<li>lib/config/read_list.cc (read_list): Adapted to use
+strlist::read instead of a custom list reading function.
+
+</ul>
+</p>
+<p>1999-08-14  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/strlist.h (class keystrlist): Split off the
+functionality to handle keyed strings ("key=value" format) into a
+seperate class.
+
+<li>lib/misc/vpwentry.h (struct vpwentry ): Adapted to using strlist
+functions.
+
+<li>lib/misc/strlist.h (class strlist ): Moved the string list
+management into its own class.
+
+<li>commands/vquota.cc: Started writing this quota management
+utility.
+
+<li>commands/vdeliver.cc (cli_main): Fixed invocation of exec*
+functions.
+
+<li>commands/vadduser.cc: Added code to set the default values of
+the new data items, and to set them when creating the user.
+
+<li>checkvpw/checkvpw.cc (main): Fixed invocation of exec*
+functions.
+
+</ul>
+</p>
+<p>1999-08-13  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/configuration.texi: Did some minor re-organization, and
+added a higher level note regarding environment variables and
+return codes for executed programs.
+
+</ul>
+</p>
+<p>1999-08-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/exec.cc (setenv): Set environment variables for quota,
+message size, message count, creation time, expiry time, personal
+data, and all the extra data.
+(exec_list): Changed interface to all the exec_* routines: the
+error message string is passed as a parameter, and the return
+value is the error return code or zero.
+
+<li>lib/misc/vpwentry_from.cc (from_uint): Modified to accept "-*"
+as the negative pattern.
+
+<li>lib/misc/utoa.cc (utoa): Moved this routine into its own module.
+
+</ul>
+</p>
+<p>1999-08-10  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/vpasswd.cc (CGI_MAIN ): Modified to call "chattr".
+
+<li>cgi/vchalias.cc (CGI_MAIN ): Modified to call "chattr".
+
+<li>daemon/dispatch.cc: Removed entries for chpass, chalias, and
+delalias.
+
+<li>daemon/chattr.cc (CMD): Merged the functions of chalias and
+chpass into this new command.
+
+<li>lib/misc/vdomain.h (class vdomain): Removed delalias command.
+
+<li>lib/misc/vdomain_deluser.cc (deluser): Removed mailbox test to
+see if the named entry was a "user".
+
+<li>commands/vdeliver.cc (inject): Handle failure properly here.
+
+</ul>
+</p>
+<p>1999-08-09  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vdeliver.cc (deliver_partial): Rewrote the delivery
+mechanism to do partial file delivery.
+(write_envelope): Rewrote the envelope handling code to use
+mystring_iter (big simplification).
+
+<li>commands/vconf2dir: Fixed non-portable increment statement.
+
+<li>commands/vadduser.cc: Added options for the extra virtual user
+data, but not the code to handle the options.
+
+</ul>
+</p>
+<p>1999-08-08  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vpasswd2cdb.cc (getpw): Call vpwentry::from_record,
+since the original text file format is compatible with its import
+routine.
+
+<li>lib/misc/vdomain_validate.cc (validate_redirect): Call exists
+instead of lookup.
+
+<li>lib/misc/vdomain_lookup.cc (exists): Wrote this routine to test
+if a name exists in a virtual domain.
+
+<li>lib/misc/vpwtable_exists.cc (exists): Added this routine to do a
+simple check if a user exists, without doing any format
+translations.
+
+<li>lib/misc/vpwentry.h (class vpwtable): Turned the "cdb" pointer
+into a void pointer to allow for easier extension to non-CDB
+formats.
+
+<li>lib/config/*: Added new default configuration items for the
+quota and expiry items.
+
+<li>lib/misc/vdomain_*.cc: Adpoted to the new vpwentry conventions.
+
+<li>lib/misc/exec.cc (setenv): Always set MAILDIR to vpw-&gt;mailbox,
+which will be empty for an alias user.
+
+<li>lib/misc/vpwentry.cc (set_defaults): Added this new routine to
+set the defaults on a vpwentry from the current configuration.
+
+<li>lib/misc/vpwentry_from.cc (from_record): Moved this routine into
+its own module, and added parsing for the new fields.
+
+<li>lib/misc/vpwentry_to.cc (to_record): Moved this routine into its
+own module.
+
+<li>lib/misc/vpwentry.h (struct vpwentry ): Added new fixed fields
+to the structure: personal, quota, msgsize, msgcount, ctime, and
+expiry.
+
+</ul>
+</p>
+<p>1999-08-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vpwentry_getset.cc (get): Added this routine to get the
+value of a data variable.
+(set): Added this routine to add a variable to the data set,
+replacing its value if it already exists.
+
+<li>lib/misc/vpwentry.cc (to_record): Rewrote this routine to output
+the new "version 1" record format.
+
+<li>lib/misc/vpwentry.h (struct vpwentry ): Expanded this structure,
+replacing the "dest" field with "mailbox" and "forwards" items,
+and added a "datastr" field.
+
+<li>lib/misc/vpwentry.cc (from_old_record): Adapted this code from
+the old vpwentry::from_record routine.
+
+<li>Released version 0.95
+
+</ul>
+</p>
+<p>1999-08-06  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vpopbull.cc (scan_bulletins): Modified the logic here
+to not fail if one of the bulletin scans fails.
+
+<li>commands/vdeliver.cc (inject): Fixed missing argv[0] in call to
+execl here.
+
+</ul>
+</p>
+<p>1999-08-05  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vpopbull.cc: Moved this program into the commands
+directory.
+(scan_bulletins): Added specific information to error messages.
+
+<li>lib/misc/exec.cc (setenv): Moved the common code to set up the
+environment for virtual users into a common routine here from
+checkvpw.cc and vdeliver.cc.
+
+</ul>
+</p>
+<p>1999-08-04  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/configuration.texi: Added sections for the new execution
+hooks.
+
+<li>checkvpw/checkvpw.cc (check): Fixed this to set the VUSER
+environment variable immediately after looking up the base user.
+
+</ul>
+</p>
+<p>1999-08-03  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>checkvpw/checkvpw.cc (main): Modified to execute the contents of
+checkvpw-postexec.
+
+<li>lib/config/showvconfig.cc.in: Built this new program template to
+show the config parameters.
+
+<li>commands/vdeliver.cc (cli_main): Make vdeliver execute a list of
+commands before and after doing the delivery.  Will set $MAILDIR
+and $VUSER.
+
+<li>checkvpw/vpopbull.cc: Moved bulletins.cc into this file, built a
+main routine, and added error logging.
+
+<li>lib/misc/exec.cc (exec_list): Created this routine to execute a
+list of commands, returning the first error as a string.
+(exec_one): Created this routine to shell and execute a single
+command using "/bin/sh -c '&lt;command&gt;'".
+
+<li>checkvpw/checkvpw.cc: Added a hook to execute a list of programs
+before and after running setuid.  The "before" programs are read
+from the global config to avoid security holes.  $HOME and $USER
+are set for both, and $MAILDIR and $VUSER are set for the "after"
+programs.
+
+</ul>
+</p>
+<p>1999-08-02  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.94
+
+<li>daemon/dispatch.cc: Commented out the "stat" and "statall"
+commands, that no longer do anything useful (the forking daemon
+causes the statistics to be meaningless).  Also removed the code
+in "dispatch" to count invocations of a particular method.
+
+<li>daemon/lookup.cc (lookup_and_validate): Fixed a false negation
+in the logic when checking for an existing virtual user.
+
+<li>lib/misc/maildir.cc (mkdirp): Fixed off-by-one bug in recursive
+case.
+
+<li>commands/vdeliver.cc: Fixed bug caused by assigning from an int
+to a bool through a pointer (since bools are only a single byte).
+
+<li>checkvpw/checkvpw.cc: Rewrote this code to do the password
+checking directly without calling up to the daemon.
+
+<li>daemon: moved lookup_baseuser into lib/misc, removed the call to
+setup a saved_state from it, and adjusted all the calls to
+lookup_baseuser in the daemon to fit.
+
+</ul>
+</p>
+<p>1999-07-30  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vdeliver.cc: Moved this program from clients into
+commands, and made it work the the CLI library.
+(cli_main): Does a call to domain.lookup now instead of a server
+call.
+(read_me): Rewrote to use config-&gt;qmail_root() instead of a
+hard-coded /var/qmail.  This is the last place (verified with
+grep) that has a hard-coded /var/qmail.
+
+</ul>
+</p>
+<p>1999-07-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/config/config_read.cc (config_read): Fixed a typo: I had
+typed '=' instead of '+' to create the full name.
+
+</ul>
+</p>
+<p>1999-07-27  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/chpass.cc (CMD): Calls the vdomain::chpass routine
+instead of doing it by hand through the vpwtable code.
+
+<li>commands/vpasswd2cdb.cc (cli_main): Removed an extraneous call
+to end_getpw.
+
+<li>lib/misc/vpwentry.h (class vpwtable): Added this new
+abstraction, a virtual password table, that contains all the
+low-level table manipulation routines.  All other code has been
+adjusted to fit this model.
+
+</ul>
+</p>
+<p>1999-07-26  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/lookup_domain.cc: Moved is_local and find_virtual into
+this file from daemon/lookup.cc.
+
+<li>daemon/lookup.cc (CMD): Converted to using vdomain::lookup.
+
+<li>daemon/check.cc (CMD): Converted to using vdomain::lookup.
+
+<li>lib/misc/vdomain_lookup.cc (lookup): Moved the daemon function
+lookup_virtuser into this method.
+
+<li>Inserted the latest cli library and adapted all the command line
+programs to handle the changes.
+
+<li>Inserted the latest mystring class and adapted all the code to
+handle it.
+
+<li>Rewrote the virtual user manipulation code from lib/misc/vuser*,
+and moved it all into the vdomain class (was struct).  Adjusted
+all other references to use this new code.
+
+</ul>
+</p>
+<p>1999-07-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.93
+
+<li>daemon/adduser.cc (CMD): Prefix the user dir destination with
+"./".
+
+<li>lib/misc/vuser_set.cc (vuser_set): Allow leading '/' in
+destination string, in addition to leading '.' and '&'.
+
+</ul>
+</p>
+<p>1999-07-22  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vsetup.cc (setup_passwd): Modified to use the new
+string iterator class.
+
+<li>lib/misc/stringiter.h (class mystring_iter): Wrote this class to
+provide an iterator over a newline (or NUL, even) seperated list
+within a string.
+
+</ul>
+</p>
+<p>1999-07-20  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vsetup.cc (setup_passwd): Changed the alias seperator
+character from ',' to '\n'.
+
+<li>lib/config/read_list.cc (read_list): Wrote this routine to read
+a config item containing a list of values.
+
+<li>lib/config/config_readlist.cc (config_readlist): Wrote this new
+routine to read a list of values from a file, newline seperated.
+
+</ul>
+</p>
+<p>1999-07-19  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/configuration.texi: Wrote this new document describing the
+new configuration structure, adapted from the now obsolete
+vmailmgr.conf.sample.
+
+</ul>
+</p>
+<p>1999-07-18  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/config/read_*.cc: Moved the overhead for maintaining the
+cache into these read functions instead of duplicating it in each
+config variable function.
+
+<li>lib/config/build-config.sh: Create a cache for each config
+variable in order to eliminate duplicate readings of a single
+variable.
+
+<li>daemon/pwentry_table.cc (operator[]): Replaced the previous
+implementation (a cache) with one that just calls getpwnam.  This
+avoids creating extra dynamic data in the form of many pwentry
+structures.
+
+<li>daemon/lookup.cc (lookup_baseuser): Removed an extraneous
+re-creation of the pwentry returned from the pwentry_table.
+
+<li>lib/config/read_*.cc: Removed the translation from '_' to '-'
+for filenames from the code and moved it into the build-config.sh
+script.  This moves the constant conversion from run-time to
+build-time.
+
+<li>lib/config/configrc.cc (configuration): Made the constructor
+take a pointer instead of a reference, which was probably the
+saner thing to do from the start.
+
+<li>lib/config/read_dir.cc (read_dir): Modified the logic here so
+that the macros for creating the config reading routines can be
+completely uniform.
+
+<li>daemon/state.cc (saved_state): Since the saved state is never
+un-saved, don't try to establish what the previous state is with
+getuid and getegid.
+
+<li>daemon/state.h: Turned the CHANGE_STATE macro into a no-op,
+since the state is already saved when doing any lookup.
+
+<li>daemon/lookup.cc (lookup_baseuser): Set up the saved state
+immediately upon successfully doing a base user lookup.
+
+<li>daemon/state.h (class saved_state): Removed the pwentry pointer
+and made the domain a non-pointer as well.
+
+</ul>
+</p>
+<p>1999-07-17  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/state.cc: Modified these routines to set up a pwentry
+before setting up the vdomain, as well as properly restoring the
+old config pointer.
+
+<li>commands/*.cc: Replaced all instances of "domain-&gt;" with
+"domain.", since "domain" is no longer a pointer.
+
+<li>clients/vdeliver.cc (main): Modified to set up a pwentry before
+setting up the vdomain.
+
+<li>clients/checkvpw.cc (set_user): Modified to set up a pwentry
+before setting up the vdomain.
+
+<li>commands/vcommand.cc (go_home): Modified to create a global
+pwentry named "user", and build the domain and config based on
+that.
+
+<li>lib/misc/vdomain.cc (vdomain): Modified the constructors to take
+a pwentry parameter to build the domain config from.
+
+<li>lib/misc/pwentry.cc: Moved this file here from daemon, added a
+"config" structure entry, and added a default constructor.
+(pwfile): Removed the pwfile_cache member, which was a kluge for
+what I thought was a bug somewhere else.
+
+</ul>
+</p>
+<p>1999-07-15  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Forwarded-ported envelope delivery re-write from 0.92.2 for
+clients/vdeliver.cc.
+
+</ul>
+</p>
+<p>1999-07-13  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/lookup.cc: Converted is_local and find_virtual to use the
+qmail_root config item.
+
+<li>Forwarded-ported logic fix from 0.92.1 for clients/vdeliver.cc.
+
+<li>clients/vdeliver.cc (inject): Use the new qmail_root config item
+to locate the qmail-queue binary.
+
+</ul>
+</p>
+<p>1999-06-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/hash_table.h: Fixed a typo in the hash table prime list
+(the last numbers were truncated).
+
+</ul>
+</p>
+<p>1999-06-14  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/FAQ.texi: Added a "troubleshooting" section, to be filled in
+as questions arrive.
+
+</ul>
+</p>
+<p>1999-06-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Modified all the sources to use the new configuration class
+members.
+
+<li>commands/vcommand.cc (go_home): Initialize the password_file
+global from config-&gt;password_file() here.
+
+<li>lib/config/configrc.cc: Totally re-wrote the configuration
+system to use a subdirectory style config, with individual files
+containing the configuration values on their first line.  The
+configuration modules are also built by a script, and broken down
+into individual object modules to reduce the size of programs that
+don't use all the options.
+
+</ul>
+</p>
+<p>1999-06-05  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/*.cc: Moved the calls to CHANGE_STATE to immediately
+after validating the user, to allow the config set up by the
+saved_state to be used immediately.
+
+<li>clients/checkvpw.cc (set_user): Set up a vdomain here and set
+the config to allow for locally-configured bulletin directories.
+(main): Moved the call to set_user higher, to allow the config to
+be used earlier to set the error maildir.
+
+<li>clients/vdeliver.cc (main): Set up a vdomain and set the config
+to its config, to load a local configuration when doing
+deliveries.
+
+<li>daemon/pwentry.cc: Removed the definitions for user_dir_rel and
+user_dir_abs, since vdomain::userdir will do the job now (it seems
+that user_dir_abs wasn't even used, too).
+
+<li>daemon/state.cc: Moved the constructor and desctuctor for
+saved_state into this object, and added a call to push a new
+configuration if state was changed successfully.
+
+<li>commands/vcommand.cc: Moved the go_home routine into here, and
+added a global "domain" pointer that will point to the current
+virtual domain.
+(go_home): Push the domain config onto the config stack.  Now all
+the command programs will use a local configuration.  This routine
+will eventually be rewritten to handle multiple domains in the
+same user.
+
+<li>commands/vadduser.cc: Converted to using a vdomain object.
+
+<li>Converted all instances of "config." to "config-&gt;" where
+appropriate (the vdomain class has a non-pointer config member, so
+it doesn't count).
+
+<li>lib/misc/server.cc: Rewrote call and connect to take as a
+parameter the socket filename to use.  server_call::call has a
+default argument now of config-&gt;socket_file to prevent having to
+change any code, but this might disappear, too.
+
+<li>lib/misc/configrc.cc: Turned the global 'config' item into a
+pointer, to allow other code to essentially push down local
+configurations onto it.  Wrote config_push and config_pop to
+assist with this.
+
+<li>commands/vaddusers.cc (add_one): Make the alias name lower case
+before using it, call vuser_adduser with the maildir argument set.
+
+<li>lib/misc/vuser_add.cc (vuser_adduser): Modified this routine to
+remove the call to userdir, forcing the maildir name to be created
+at a higher level.
+
+</ul>
+</p>
+<p>1999-06-04  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/configrc.cc (configuration): Eliminated the #defined
+default constants, as they are used only once, and moved them
+directly into the default configuration constructor.
+
+<li>lib/misc/configrc.h (class configuration ): Added a "parent"
+member item that points to the object from which the defaults for
+this configuration was set (set to NULL in the default object).
+
+<li>lib/misc/vdomain.cc: Created this construct to represent a
+virtual domain.  Copied the functionality from userdir.cc into
+here (with the plan of removing userdir.cc in the future).  This
+will become the status-holder for multiple domains within a single
+real user.
+
+<li>lib/misc/configrc.cc (configuration): Added a new constructor
+that copies the values from a set of defaults and reads in a
+config file to override those defaults.  To be used for local
+configuration handling.  Relegated the default constructor to only
+setting the default values, and added a new global const object
+config_defaults to hold these.
+
+<li>commands/*: Added a call to go_home in every cli_main.
+
+<li>commands/go_home.cc (go_home): Wrote this routine to chdir to
+the user's HOME directory.
+
+</ul>
+</p>
+<p>1999-06-03  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/listvdomain.cc (cli_main): I forgot to check the return
+value of start_getpw here, leading to a core dump when the
+password table can't be opened.  Fixed.
+
+</ul>
+</p>
+<p>1999-06-01  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vsetup.cc (setup_qmail_default): Changed the mode of
+the created .qmail-default file to 0444 (minus umask) instead of
+0666 to prevent qmail from complaining on systems where umask
+defaults to 002 instead of 022, and to prevent inadvertent editing
+of the .qmail-default file.
+
+</ul>
+</p>
+<p>1999-05-30  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.92
+
+</ul>
+</p>
+<p>1999-05-28  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/vdeliver.cc: Rewrote the alias delivery routines to send
+the email to qmail-queue instead of qmail-inject, since
+qmail-inject will attempt to reformat the message.
+
+</ul>
+</p>
+<p>1999-05-27  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/check.cc (CMD): Added a check to ensure that checking the
+password for an alias fails.
+
+<li>doc/*: Changed references from qcc.sk.ca to em.ca.
+
+</ul>
+</p>
+<p>1999-05-26  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/addaliasp.cc (CMD): Added this new command to add an
+alias with a password.
+
+<li>doc/vmailmgr-cgi.texi: Updated the documentation for vaddalias.
+Changed all instances of "necessary" to "required".
+
+<li>cgi/vaddalias.cc (CGI_MAIN ): Now allows for an optional new
+password field pair, and calls addaliasp if they are not empty.
+
+<li>lib/misc/server.cc (server_call): Added a new server_call for 5
+parameters.
+
+<li>daemon/log.cc (logcommand): Added a new logcommand routine to
+handle 5 parameters.
+
+<li>daemon/dispatch.cc: Modified the dispatch entry for addalias.
+
+<li>daemon/chpass.cc (CMD): Removed the custom password checking
+since it is now merged into lookup_and_validate.
+
+<li>daemon/chalias.cc (CMD): Call lookup_and_validate with the
+"userpass" flag set to true to allow owners of virtual aliases set
+up with a password to change their alias.
+
+<li>daemon/lookup.cc (lookup_and_validate): Modified to optionally
+do comparisons against the virtual user's password if the
+comparison against the administrator's password fails.  Removed
+the allowance for empty passwords.  Made all the password
+mis-match messages the same.  The admin password check is done
+before the virtual user check to avoid giving away information
+about virtual users.
+
+<li>commands/vaddalias.cc (cli_main): Set passwords on aliases by
+passing in a '-p' or '--password' flag.
+
+<li>lib/misc/vuser_add.cc (vuser_addalias): Modified to allow
+passwords on aliases.
+
+</ul>
+</p>
+<p>1999-05-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.91
+
+</ul>
+</p>
+<p>1999-05-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/chalias.cc (CMD): Bug fix: was passing "false" for
+"mustexist" to lookup_and_validate, when it should have been
+"true".
+
+<li>commands/vdelalias.cc, commands/vdeluser.cc,
+commands/vaddusers.cc, commands/vaddalias.cc,
+commands/vpasswds.cc, commands/vchalias.cc: Added a mechanism to
+count and report the number of errors encountered.
+
+<li>doc/vmailmgr-cgi.texi: Added a chapter for the chalias command.
+Also added sections for vdelalias and vdeluser, as well as sorting
+the sections into alphabetical order.
+
+<li>cgi/vchalias.cc: Wrote the CGI program to call the chalias
+command.
+
+<li>doc/vchalias.pod: Wrote the documentation page for the vchalias
+command.
+
+</ul>
+</p>
+<p>1999-05-15  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/configrc.cc (DEFAULT_DEFAULT_USERNAME): Changed the
+default default username from '*' to '+', to avoid shell
+screwups.  Updated documentation.
+
+</ul>
+</p>
+<p>1999-05-04  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/checkvpw.pod: Fixed filename glitch -- replaced all
+instances of virtualhosts with virtualdomains.
+
+</ul>
+</p>
+<p>1999-05-01  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vpwentry_putpw.cc (putpw): Changed logic of "onlyadd"
+parameter.  If set, will fail if the name already existed.  If not
+set, will fail if the name did not already exist.
+
+<li>daemon/dispatch.cc: Added a dispatch entry for chalias.
+
+<li>daemon/chalias.cc (CMD): Created this server command to change
+an existing alias to a new destination, using the new vuser_set.
+
+<li>daemon/adduser.cc (CMD): Changed to use vuser_set.
+
+<li>daemon/addalias.cc (CMD): Changed to use vuser_set.
+
+<li>lib/misc/vuser_add.cc: Changed to use vuser_set.
+
+<li>commands/vadduser.cc (add_user): Changed to use vuser_set.
+
+<li>lib/misc/vuser_set.cc (vuser_set): Renamed vuser_add to
+vuser_set, and moved it into this file.  vuser_set can be used to
+change existing entries as well as to add new entries.
+
+<li>commands/vrehash.cc (lock_dir): Set permissions on created CDB
+file to 0600.
+
+<li>commands/vpasswd2cdb.cc (cli_main): Set permissions on created
+CDB file to 0600.
+
+<li>lib/misc/vpwentry_putpw.cc (putpw): Set permissions on created
+CDB file to 0600.
+
+<li>lib/misc/vpwentry_delpw.cc (delpw): Set permissions on created
+CDB file to 0600.
+
+<li>clients/vdeliver.cc: Changed all I/O to use fdbuf primitives.
+(deliver): Changed permissions on created file to 0666 to 0600
+(mail should be private).
+
+</ul>
+</p>
+<p>1999-04-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.90.2
+
+</ul>
+</p>
+<p>1999-04-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/userdir.cc (userdir): Use the multiple-argument
+mystring constructor to make pasting the slices together more
+efficient.
+
+<li>daemon/main.cc: Added include of &lt;stdio.h&gt; to pull in perror
+properly.
+
+</ul>
+</p>
+<p>1999-04-08  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.90.1
+
+</ul>
+</p>
+<p>1999-04-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vpwentry_putpw.cc: Removed include of errnos.h
+
+<li>lib/misc/md5-crypt.c: Added definitions for MIN and MAX if they
+aren't defined.
+
+</ul>
+</p>
+<p>1999-04-05  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/vmailmgr.conf.sample: Removed the entry for
+cdb-password-file, as that variable is not used.
+
+</ul>
+</p>
+<p>1999-04-04  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.90
+
+<li>doc/FAQ.texi: Noted that the C++ libraries are no longer
+needed.
+
+<li>clients/bulletins.cc (stat_maildir): Fixed two bugs: timestamp
+file was named "maildir/cur/.timestamp" instead of just
+"maildir/.timestamp"; timestamp file was opened for writing
+without a mode, causing the resulting file to have an
+indeterminate mode.
+
+<li>doc/FAQ.texi: Added an answer regarding IMAP support.
+
+</ul>
+</p>
+<p>1999-04-03  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc (handle_connection): Only print out the "Accepted
+connection" message if the verbose flag is set.
+
+</ul>
+</p>
+<p>1999-04-01  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/md5-crypt.c (md5_crypt_r): This routine depended on the
+result of "strncpy" pointing to the end of the destination
+string.  This is non-standard behavior.  Fixed such that the "cp"
+pointer tracks its position manually.
+
+<li>cgi/listvdomain.cc: Converted to fdbuf.
+
+<li>daemon/main.cc (usage): Converted to fdbuf.
+
+<li>daemon/log.cc: Converted to fdbuf.
+
+<li>daemon/map_table.cc (map_table): Converted to fdbuf.
+
+<li>daemon/list_table.cc (list_table): Converted to fdbuf.
+
+<li>commands/*: Converted from iostream to fdbuf.
+
+<li>lib/cli/main.cc: Use the new "operator&lt;&lt;" methods of fdobuf.
+
+<li>lib/misc/validate.cc (validate_redirect): Converted from using
+ostrstream to mystring for growing error messages.
+
+<li>lib/misc/configrc.cc (read_config): Use the new "operator&lt;&lt;"
+methods of fdobuf for writing messages.
+
+<li>lib/misc/passwdfn.cc: Converted to using fdbuf objects.
+
+</ul>
+</p>
+<p>1999-03-31  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/pwcrypt.cc: Adapted these routines to using the GNU MD5
+library and the md5_crypt routine.
+(crypt_cmp): Revised the algorithm here to use the old MD5 routine
+only for old passcodes, md5_crypt for hashes starting with "$1$",
+and crypt otherwise.  This should be compatible with all
+implementations.
+
+<li>lib/misc/configrc.cc (read_config): Modified to use fdibuf
+instead of ifstream.
+(cmp): Fixed logic to properly parse "STR *= *STR" instead of
+"STR *(=+ *)+STR".
+
+<li>Changed the copying policy to GPL.
+
+</ul>
+</p>
+<p>1999-03-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.89.1
+
+<li>configure.in: Add a --enable-md5 flag to set USE_MD5.
+
+<li>lib/misc/pwcrypt.cc: Imported implementation of crypt_cmp and
+pwcrypt from 0.87, using USE_MD5 as a selector.
+
+</ul>
+</p>
+<p>1999-03-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.89
+
+<li>daemon/main.cc (handle_connection): Move the exit(0) out of the
+if block so that the child always exits.
+
+<li>daemon/fork.cc (do_fork): Bump up the fork counters in the child
+as well as the parent so that the accounting commands work
+properly.
+
+<li>clients/bulletins.cc (stat_maildir): Fixed type: open the
+timestamp file for output, not the maildir.
+
+</ul>
+</p>
+<p>1999-03-20  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/bulletins.cc (stat_maildir): The timestamp on the "cur"
+directory is unreliable.  Create a zero-length ".timestamp" file
+and use its modification mode for last-login information.
+
+</ul>
+</p>
+<p>1999-03-18  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/listdomain.cc (CMD): Fixed a non-incrementing loop
+counter.
+
+<li>daemon/fork.cc (handle_children): Now checks for both pid == -1
+and pid == 0 to terminate the wait loop.
+
+<li>lib/misc/vpwentry_putpw.cc (putpw): If the input file does not
+exist, skip the loop and add the record to a new output file.
+
+<li>lib/cdb++/cdb_reader.cc (cdb_reader): Set the failed flag to the
+result of opening the file.
+
+<li>lib/misc/vpwentry_putpw.cc (putpw): Fixed inverted boolean bug.
+
+<li>daemon/lookup.cc (lookup_baseuser): Fixed bug: the pwentry
+pointer returned by operator[] on the pwentry_table gets deleted
+when the pwentry_table goes out of scope (and all kinds of weird
+things happen to the data).
+
+<li>daemon/pwentry.cc (pwfile): Cache the value of pwfile for future
+calls.
+
+<li>daemon/lookup.cc (lookup_baseuser): Use "right" instead of the
+silly pointer increment logic to get the virtual name substring.
+
+</ul>
+</p>
+<p>1999-03-17  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/dispatch.cc (dispatch_cmd): Remove all fork handling from
+this routine.
+
+<li>daemon/main.cc (handle_connection): Call do_fork immediately
+after accepting the connection.
+
+</ul>
+</p>
+<p>1999-03-16  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vsetup.cc (setup_qmail_default): Set the initial value
+of .qmail-default to "|@BINDIR@/vdeliver".
+
+<li>commands/vrehash.cc: Rewrote to use CDB functions.
+
+<li>daemon/listdomain.cc (CMD): Send output to 'fd' instead of
+hard-coded file descriptor 2.
+
+<li>daemon/dispatch.cc (dispatch_cmd): Pass the file descriptor to
+the dispatched function.
+
+<li>daemon/main.cc (handle_connection): Modified logic to better
+suit the always-fork mentality.
+
+<li>daemon/dispatch.cc (dispatch_cmd): Changed logic to always
+fork.
+
+<li>At this point, all cache support in vmailmgrd has been removed,
+and all virtual password table functions will read CDBs.
+
+<li>daemon/lookup.cc: Converted the functions here to using the
+tables instead of the caches.
+
+<li>daemon/pwentry_table.cc (pwentry_table): Converted the
+implementation of pwentry_reader into this class.
+
+<li>daemon/hash_table.h (class hash_table): Fixed a long-standing
+const method issue.
+
+<li>daemon/list_table.cc (list_table): Converted the implementation
+of list_reader into this class.
+
+<li>daemon/map_table.cc (map_table): Converted the implementation of
+map_reader into this class.
+
+<li>daemon/listdomain.cc (CMD): Removed the use of the vpwentry
+cache table.
+
+<li>lib/misc/vpwentry_get.cc (rewind_getpw): Wrote this routine to
+rewind an open cdb table witout re-opening it.
+(getpw): Converted to using autodelete.
+
+<li>daemon/chpass.cc (CMD): Removed the use of the vpwentry cache
+table.
+
+<li>daemon/lookup.cc (lookup_virtuser): Removed the use of the
+vpwentry cache table.
+
+<li>daemon/pwentry.h (struct pwentry): Removed the vpwtable entry.
+
+</ul>
+</p>
+<p>1999-03-15  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vpwentry_*.cc: Append ".cdb" to the filename for the
+CDB file name.
+
+<li>lib/misc/configrc.cc: Removed the cdb_password_file entry.
+
+</ul>
+</p>
+<p>1999-03-13  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vpwentry_putpw.cc (putpw): Converted to using CDB
+functions.
+
+<li>commands/passwd2cdb.cc (cli_main): Converted to use to_record.
+
+<li>lib/misc/vpwentry.cc (to_record): Wrote this one-liner to build
+a CDB record from the entry.
+
+<li>lib/misc/vpwentry_delpw.cc (delpw): Converted to using CDB
+functions.
+
+<li>lib/misc/vpwentry_get.cc (start_getpw): Rewrote to use
+vpwentry::from_record.
+
+<li>lib/misc/vpwentry_getpw.cc (getpw_byname): Rewrote to use
+vpwentry::from_record.
+
+<li>lib/misc/vpwentry.cc (from_record): Wrote this routine to build
+a vpwentry from a CDB record.
+
+</ul>
+</p>
+<p>1999-03-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/misc/vpwentry_getpw.cc (getpw_byname): Converted to using
+CDB functions.
+
+<li>lib/misc/vpwentry_get.cc: Converted to using CDB functions.
+
+<li>lib/misc/configrc.cc: Added support for configuring the CDB
+password table name.
+
+<li>commands/passwd2cdb.cc: Wrote this program to convert a standard
+virtual password table into a CDB table.  The initial record
+format is identical to the old to reduce library conversion
+issues.
+
+<li>lib/misc/vpwentry_get.cc (start_getpw): This routine now returns
+bool to indicate if the table was opened successfully.
+
+<li>Major reorganization of the libraries and header files.  All the
+libraries are in subdirectories under "lib", and the headers under
+"include" (with a pile of symlinks).
+
+</ul>
+</p>
+<p>1999-03-11  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.88
+
+<li>configure.in: Check for libinet and libsocket.
+
+</ul>
+</p>
+<p>1999-03-10  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/vmailmgr-cgi.texi (Top): Removed warning about passwords
+being limited to eight characters.
+
+<li>commands/vpasswds.cc (change_one): Removed warning about
+passwords being truncated to eight characters.
+
+<li>lib/passwdfn.cc (getpasswd_interactive): Removed warning about
+passwords being truncated to eight characters.
+(getpasswd_stdin): Removed another eight character warning.
+
+</ul>
+</p>
+<p>1999-03-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/pwcrypt.cc: Add a passcode type digit to the MD5 hashes on
+output, and check for this digit on comparison to determine what
+type of hashing to use.
+
+</ul>
+</p>
+<p>1999-03-04  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/check.cc (CMD): Tidied up result string creation code.
+
+<li>lib/vpwentry_getpw.cc (getpw_byname): Copied logic from getpw.
+
+<li>lib/vpwentry_get.cc (getpw): Fixed minor logic flaws.
+
+<li>lib-dbi/passcode.cc: Added a stub for MD5 authentication.
+
+<li>daemon/chpass.cc (CMD): Use renamed pwcrypt.
+
+<li>daemon/adduser.cc (CMD): Use renamed pwcrypt.
+
+<li>commands/vadduser.cc (add_user): Use renamed pwcrypt.
+
+<li>lib/vuser_add.cc (vuser_adduser): Use renamed pwcrypt.
+
+<li>lib/vuser_chpass.cc (vuser_chpass): Use renamed pwcrypt.
+
+<li>lib/pwcrypt.cc (crypt_cmp): Modified to automatically handle MD5
+hashed passcodes.
+Renamed encrypt to pwcrypt, which calls encrypt_md5 to produce MD5
+hashed passcodes.
+
+<li>Completed conversion of source packaging from custom makefiles
+to automake.
+
+</ul>
+</p>
+<p>1999-02-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.87
+
+<li>Removed my kludged handling for building shared libraries.  This
+greatly simplifies the process of moving to both automake and
+libtool.  The executables are somewhat larger, but still come in
+under about 25K each (on i386 Linux).
+
+<li>clients/bulletins.cc (scan_bulletins): Skip scanning the local
+bulletin directory if the user is non-virtual.
+
+<li>clients/checkvpw.cc (struct user_data): Added a non_virtual flag
+to this data, indicating that the user is not a virtual user.
+(main): Pass the non_virtual flag into scan_bulletins.
+
+<li>lib/ac-wait.h: Moved the #include ladder that is required to use
+wait(2) functions here.
+
+<li>lib/ac-dirent.h: Moved the #include ladder that is required to
+use dirent functions here.
+
+<li>lib/ac-time.h: Moved the #include ladder that is required to use
+time functions here, and rewrote all the files that include either
+&lt;time.h&gt; or &lt;sys/time.h&gt; to instead include "ac-time.h"
+
+<li>commands/vpasswds.cc (cli_main): Removed call to srandom.
+
+<li>commands/vpasswd.cc (cli_main): Removed call to srandom.
+
+<li>commands/vaddusers.cc (cli_main): Removed call to srandom.
+
+<li>commands/vadduser.cc (cli_main): Removed call to srandom.
+
+<li>lib-cli/main.cc (main): Call srandom here to give all the CLI
+programs a properly initialized random function automatically.
+
+</ul>
+</p>
+<p>1999-02-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc: All signal handlers call signal to re-enable
+signal handling on systems that reset signals.
+
+<li>daemon/fork.cc (handle_children): Re-assert the SIGCHLD signal
+handler after a signal is received, since some systems will reset
+the behavior of signals after they've been received.
+
+</ul>
+</p>
+<p>1999-02-22  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib-cgi/cgi-base.cc (main): Eliminated the timezone setup since
+it is totally unnecessary.
+
+</ul>
+</p>
+<p>1999-02-09  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib-dbi/user.h: Moved the password validation method out of the
+ruser/vuser classes into struct passcode.  This class may
+eventually be split into multiple classes, one per passcode type.
+
+</ul>
+</p>
+<p>1999-02-06  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.86
+
+<li>clients/bulletins.cc: Changed logic in all routines to not fail
+if an error occurrs.
+(link_file): Fixed several logic flaws.
+
+</ul>
+</p>
+<p>1999-01-30  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/bulletins.cc: Completed prototype code.
+
+</ul>
+</p>
+<p>1999-01-28  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/bulletins.cc (scan_bulletins): Roughed-in bulletin
+scanning support.
+
+<li>clients/checkvpw.cc (main): Added call to scan bulletins.
+
+<li>lib/configrc.h (class configuration ): Added variables to be
+used to set up bulletin directories.
+
+</ul>
+</p>
+<p>1999-01-26  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vadduser.cc: Modified to accept a "directory" argument
+of where to put the user's mailbox.
+
+</ul>
+</p>
+<p>1999-01-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Rewrote various sources to take advantage of new mystring
+library constructor functions.
+
+<li>Inserted revised mystring library.
+
+</ul>
+</p>
+<p>1999-01-09  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.85
+
+<li>daemon/vpwentry_cache.cc (dirname): Fixed stupid bug -- used
+"right" instead of "left" to get the directory part of the
+filename.  This bug was introduced by the following change.
+
+<li>All files: reworked code to remove cases where an automatic
+conversion from type mystring to "const char*' was expected.
+Instead, all the code uses the c_str() function in mystring.
+
+<li>Added a note in the FAQ regarding the default username.
+
+<li>lib-cli/main.cc: Rewrote the CLI library to remove dependance on
+the GNU libiberty getopts.
+
+</ul>
+</p>
+<p>1998-12-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/vdeliver.cc (main): Changed the default for adding the
+leading "From " line to false.
+
+<li>Released version 0.84
+
+</ul>
+</p>
+<p>1998-12-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/response_read.cc (read): Removed the __GNUG__ cruft here
+that was only really necessary to optimize on old "mystring" use
+(and probably only added nearly useless complexity even then).
+
+<li>lib/userdir.cc (userdir): Added a work-around for the apparent
+egcs inlining bug to fix those core dumps when running vadduser
+and friends.  Using egcs -finline-functions causes them to core
+dump, without inlining everything works OK.
+
+</ul>
+</p>
+<p>1998-12-09  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vadduser.cc (cli_main): Fixed off-by-one error
+introduced by the use of lib-cli.
+
+</ul>
+</p>
+<p>1998-12-08  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>configure.in: Added a check to determine if the C++ compiler is
+buggy and abort if so.
+
+</ul>
+</p>
+<p>1998-12-03  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>configure.in: Modified the tests for -fno-exceptions and
+-fno-rtti to actually run the C++ compiler and check its result.
+
+</ul>
+</p>
+<p>1998-12-02  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/*.cc: Refitted all the command programs to use lib-cli.
+
+</ul>
+</p>
+<p>1998-11-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vaddalias.cc: Refitted to use lib-cli.
+
+<li>lib-cli/main.cc: Wrote a top-level command-line interface
+helper, which handles automatic help-screen generation, short and
+long argument parsing, and will eventually handle switching
+between "standard" command use and server-call usages.
+
+</ul>
+</p>
+<p>1998-11-28  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/listvdomain.cc: Wrote this program to list the contents
+of a virtual domain.
+
+<li>configure.in: Added a somewhat poor hack to handle support for
+static vs shared libraries.
+
+<li>lib/vpwentry_get.cc: added start_getpw, end_getpw, and getpw
+routines.
+
+</ul>
+</p>
+<p>1998-11-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc: Fixed handling of aborted and timed out
+requests.  A timed out request will result in two error messages,
+one from the alarm, and one from the failed read.
+
+</ul>
+</p>
+<p>1998-11-07  Bruce Guenter  &lt;bguenter@hal.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.83
+
+<li>doc/vmailmgr-cgi.texi: Added a section to describe the use of
+the listvdomain CGI.
+
+<li>cgi/listvdomain.cc (show_dest): Split original show_user into
+show_dest which calls show_mbox or show_alias.
+(show_mbox): Modified output to show mailbox destination.
+(CGI_MAIN ): Accepts form inputs mboxlink and aliaslink, which are
+links inserted on each mailbox or alias name, with '%' replaced by
+the mailbox or alias name.
+
+</ul>
+</p>
+<p>1998-10-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc (handle_connection): It appears that accept may
+return with an error if a signal occurred while the accept was
+being processed.  So, loop around accept until a valid fd is
+returned.
+
+</ul>
+</p>
+<p>1998-10-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/cgi-*: Moved these files into lib-cgi.
+
+</ul>
+</p>
+<p>1998-10-01  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>*/*.cc, */*.h: Changed all remaining instances of "const
+mystring&" to "mystring".
+
+</ul>
+</p>
+<p>1998-09-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/server.cc, lib/response*.cc: Changed all instances of "const
+mystring&" to "mystring".
+
+<li>cgi/listvdomain.cc (CGI_MAIN ): Forgot to output a content type
+before the HTML content.  Fixed.
+(show_domain): The user list is now sorted on output.
+
+<li>lib/cgi-args.cc: Changed all instances of "const mystring&" to
+"mystring".
+
+<li>lib/cgi-base.cc: Exported content_type function.
+Changed all instances of "const mystring&" to "mystring".
+
+</ul>
+</p>
+<p>1998-09-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.82
+
+</ul>
+</p>
+<p>1998-09-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc (exit_fn): Check the count of active forked
+processes and sleep until they are all no longer active.
+
+<li>daemon/daemon.h: Moved parts of this file into command.h and
+log.h.
+
+<li>daemon/*.cc: Replaced all instances of "cout" that produce log
+messages with "log()" or "log(msg)".
+
+<li>daemon/log.cc (log): Added new routine that prefixes log lines
+with "[pid] " if the log is being output from a child process.
+
+<li>cgi/listvdomain.cc (show_domain): Fixed loop logic to properly
+truncate the buffer when repeating.  Set up the output to display
+a table instead of a list.
+(show_user): Added this routine to output a single user, doing a
+lookup to determine if the name is a mailbox or alias.
+
+<li>daemon/dispatch.cc: Changed all the entries that would modify a
+user to be "forked" methods.
+
+</ul>
+</p>
+<p>1998-09-23  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/listdomain.cc (CMD): write_buf returns true on success,
+not false.  Fixed.
+
+<li>lib/response_message.cc (message): Fixed a minor bug: the "msg"
+portion of the response was treated as a NUL-terminated C string
+instead of as binary data, causing potential truncation when used
+with the listdomain facility.
+
+</ul>
+</p>
+<p>1998-09-21  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/checkvpw.cc (authenticate): Modified to handle extra
+maildir value in string, eliminating an extra lookup.
+
+<li>daemon/check.cc (CMD): Modified return string to include a
+maildir for virtual users.
+
+<li>daemon/fork.cc: Removed all the code that dealt with process
+slots to fix a race condition: the forked process could exit
+before the parent registers it as a child, causing the active
+process counts to become incorrect and eventually prevent any
+further forks.
+
+</ul>
+</p>
+<p>1998-09-20  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc (handle_connection): Modified to use new fork
+logic.
+(usage): Added -v/-V option to usage message.
+
+<li>daemon/dispatch.cc (dispatch_cmd): Fixed logic of "did_fork"
+flag to become two flags: needs_write and needs_exit.
+
+<li>daemon/main.cc (main): Removed use of atexit(exit_fn) to
+automatically remove the socket file, since it must not be removed
+when exiting from a forked routine.
+
+<li>daemon/dispatch.cc (dispatch_cmd): dup2 returns -1, not
+non-zero, on error.  Fixed.
+
+<li>doc/vmailmgr.pod: Added the full list of programs that are part
+of this package to a "SEE ALSO" list.
+
+</ul>
+</p>
+<p>1998-09-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/checkvpw.cc (main): Fixed design flaw in the "missing
+maildir" design caused by setting the MAILDIR environment variable
+before checking for the existance of the maildir.
+(find_maildir): Changed search logic -- if no matching string is
+found, indicate that the last argument is the "maildir" argument.
+(main): Removed several redundant checks that were a result of the
+above change.
+
+</ul>
+</p>
+<p>1998-09-09  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/response_read.cc (read_response): Fixed the missing "break"
+in the switch statement.
+
+</ul>
+</p>
+<p>1998-09-08  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc (handle_intr): Ignore PIPE signals while exiting,
+as there is a potential for an infinite loop to occur if stdout is
+a pipe that closes before this program exits.
+
+</ul>
+</p>
+<p>1998-09-05  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/response_read.cc (receive_string): Moved this routine here
+from lib/server.cc.
+(read): Moved the former implementation of response::response(int)
+into a static read_response routine, and renamed it response::read.
+
+<li>lib/server.cc: Fixed several compile bugs.
+
+<li>cgi/listvdomain.cc: Fixed compile bugs, still not tested.
+
+</ul>
+</p>
+<p>1998-08-21  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/listvdomain.cc (CGI_MAIN ): Completed the preliminary
+implementation of this CGI.
+
+<li>lib/server.cc (call): Modified to use the new response
+constructor to read the response from the client.
+
+<li>lib/response.h (struct response): Added a constructor to read
+the data from a file descriptor.
+
+</ul>
+</p>
+<p>1998-08-13  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/lookup.cc (lookup_and_validate): Fixed the behavior when
+the password table contains a "default" user, the requested user
+does not exist, and the "mustexist" flag is set.
+
+</ul>
+</p>
+<p>1998-07-31  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/listvdomain.cc: Started this CGI program to list the users
+in a virtualdomain, using the new "listdomain" server function.
+
+<li>lib/server.h (class server_call): Added a routine 'socket' to
+return the open socket.
+
+<li>lib/server.cc (call): Modified to record the file descriptor for
+the connection and to close it when the server_call is destructed.
+
+</ul>
+</p>
+<p>1998-07-26  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/dispatch.cc (dispatch_cmd): In the case of a forked
+dispatch, move the output to fd #2 (usually stderr), to give it a
+constant location.
+
+<li>lib/response.h (struct response): Added the 'maxsize' constant
+representing the maximum size of any one transmitted message.
+
+<li>daemon/listdomain.cc (CMD(listdomain)): Completed implementation
+of this command.
+
+<li>daemon/lookup.cc: Moved the functions is_local and find_virtual
+into this file from dispatch.cc.
+
+</ul>
+</p>
+<p>1998-07-21  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/listdomain.cc (CMD(listdomain)): Started building this
+routine to list the users in a virtual domain.
+
+</ul>
+</p>
+<p>1998-07-20  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc (parse_options): Added support for a "verbose"
+flag.
+
+<li>daemon/fork.cc (do_fork): Wrote this new routine to fork a new
+process and record its pid in a table (if slots are available in
+the table).
+(handle_children): Wrote this new routine to handle any children
+that were forked and have exited.
+
+<li>daemon/main.cc (handle_connection): Added support for commands
+that cause forked connections.
+
+<li>lib/configrc.h (class configuration ): Added new configuration
+variable "max_fork" -- the maximum number of forked processes to
+handle.
+
+<li>daemon/main.cc (handle_connection): Modified this routine to
+simply close the socket fd and continue if the previous operation
+forked (the other "half" of the fork will handle the output).
+
+<li>daemon/dispatch.cc (struct dispatch ): Added a field to this
+structure to indicate that the operation needs to fork.
+
+</ul>
+</p>
+<p>1998-07-09  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.80
+
+<li>clients/checkvpw.cc (getdata): Fixed a longstanding error in
+setting the password/stamp fields.  Fortunately, this error had no
+impact at all on the data we use, but would have been immediately
+visible if we were to try to use the timestamp.
+
+<li>daemon/lookup.cc (lookup_virtuser): Added code to look up a
+default user if the lookup of a named user fails.
+
+<li>lib/configrc.h (class configuration ): Added a new configuration
+variable "default_username".
+
+<li>clients/vdeliver.cc (build_command): Fixed a bug that would
+cause an infinite loop when delivering to multiple destinations.
+(build_command): Moved the appending of the hostname from enqueue
+into here, to allow it to be added on each recipient.
+
+</ul>
+</p>
+<p>1998-06-17  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>doc/vrehash.pod: Started man page for vrehash.
+
+<li>commands/vrehash.cc: Wrote this program to move all users
+directories around into the proper hashed directory (see the man
+page).
+
+<li>commands/vpasswds.cc (change_one): Fixed incorrect status
+message (was "vpasswd:" should be "vpasswds:").
+
+</ul>
+</p>
+<p>1998-06-15  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/maildir.cc (make_maildir): Modified this routine to make all
+the directories leading up to the named directory.
+
+<li>lib/configrc.h (class configuration ): Added the fields
+user_dir_bits and user_dir_slices to support userdir.
+
+<li>lib/vuser_add.cc (vuser_add): Modified an error message to make
+it more informative.
+
+<li>daemon/pwentry.cc (user_dir_abs): Modified to use userdir.
+(user_dir_rel): Modified to use userdir.
+
+<li>lib/vuser_add.cc (vuser_adduser): Modified to use userdir.
+
+<li>lib/userdir.cc (userdir): Wrote this routine, which produces a
+relative user directory name, including a hashed-out path and
+subdirectories, from a username.
+
+</ul>
+</p>
+<p>1998-06-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/checkvpw.cc (main): Added a test to check if the user's
+maildir exists and, if not, set the maildir to the configured
+"error_maildir" string.
+
+<li>daemon/main.cc (handle_intr): Fixed shutdown logic to handle
+both cases: interrupted while handing a connection, or while
+waiting for a connection.
+
+<li>lib/configrc.h (class configuration ): Added new configuration
+variable "error_maildir", which is a read-only maildir that
+contains an error mail message.
+
+</ul>
+</p>
+<p>1998-06-11  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/configrc.cc (configuration): Commented out the code to read
+a local configuration file.
+
+<li>lib/configrc.h: Moved the DEFAULT_* definitions out of here and
+into configrc.cc again.
+
+<li>Backed out all the vdomain and configuration patches, in order
+to fix all the confusion I had been generating.
+
+<li>daemon/main.cc (main): Changed the "interrupt" logic to exit
+after the current request instead of potentially exiting during
+the request (and leaving files in a indeterminate state).
+
+</ul>
+</p>
+<p>1998-06-09  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/vdomain.h (struct vdomain): Added a "config" item to this
+class.
+
+</ul>
+</p>
+<p>1998-06-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/state.h (class saved_state): Added code to effectively
+push/pop a local configuration when entering a saved_state.
+
+<li>*/*.cc: Changed the use of the "config" variable to account for
+it being a pointer.
+
+<li>commands/*.cc: Added the line "config = local_config();" to the
+main routine before anything else is executed.
+
+<li>lib/configrc.cc (local_config): Added this routine to create a
+local configuration based on the given home directory.
+
+<li>lib/configrc.h: Moved the DEFAULT_* definitions out of here and
+into configrc.cc (the only place they are referenced).
+Modified the constructors to support "stacking" of configurations.
+Made the global "config" variable into a pointer to allow it to
+change.
+
+<li>daemon/vdomain.h (struct vdomain): Wrote this new structure to
+encapsulate a virtual domain.  These domains are stored in a hash
+table "vdomains", indexed by base directory.
+
+<li>daemon/chpass.cc, daemon/lookup.cc: Adjusted to use the new
+vdomains global.
+
+<li>daemon/pwentry.h (struct pwentry): Removed the vpwentry_cache
+from this structure.  This will eliminate the expensive lookups at
+startup (the file "passwd" is looked up for each real user) and a
+significant amount of memory overhead.
+
+</ul>
+</p>
+<p>1998-06-05  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.79
+
+</ul>
+</p>
+<p>1998-06-01  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/passwdfn.cc: Got rid of __GLIBC__ ifdef for crypt.h
+
+<li>lib/pwcrypt.cc: Got rid of __GLIBC__ ifdef for crypt.h
+
+</ul>
+</p>
+<p>1998-05-31  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/configrc.h: Removed the comment regarding DO_SHADOW.
+
+<li>daemon/pwentry_cache.cc: Modified the reader to make only a
+single pass through the password and shadow password files.
+
+<li>lib/configrc.h: Renamed lib/config.h to this to avoid name
+conflicts with the autoconf/configure-generated config.h.
+
+<li>various: Fixups mandated by the use of autoconf.
+
+</ul>
+</p>
+<p>1998-05-29  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/dispatch.cc: Made the "echo" daemon command conditionally
+compiled if TEST_DAEMON is defined.
+
+<li>daemon/vpwentry_cache.cc: Added code to log when the virtual
+password caches are loaded/reloaded.
+
+<li>daemon/pwentry_cache.cc: Added code to log when the password
+cache is loaded/reloaded.
+
+<li>commands/vsetup.cc (setup_passwd): Modified to use the new
+postmaster config variables.
+
+<li>lib/config.cc (read_config): Changed the "postmaster"
+configuration variable into "postmaster_email" and added
+"postmaster_aliases".
+
+</ul>
+</p>
+<p>1998-05-27  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.78
+
+<li>lib/vpwentry_putpw.cc (putpw): Fixed logic to deal with an
+existant but non-readable original password file.
+
+<li>lib/vuser_add.cc (vuser_add): Changed the order of creating the
+maildir and adding the user to the passwd file.  This allows the
+maildir to be erased if adding the user fails, since the newly
+created maildir is guaranteed to be empty.
+
+<li>lib/maildir.cc (make_maildir): Modified the code to remove any
+newly-created directories if creation of any directory fails.
+
+<li>lib/passwdfn.cc (getpasswd_stdin): Changed use of "gets" to
+"cin.get".
+
+</ul>
+</p>
+<p>1998-05-26  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vpasswd.cc (main): Changed the "fprintf" to use
+IOStreams.
+
+<li>lib/passwdfn.cc (getpasswd_*): Print a warning if the password
+is longer than 8 characters.
+
+<li>commands/vpasswds.cc: Wrote this new program to change the
+passwords of a list of users.  The input for this list is taken
+from standard input and is of the form "name password".  Anything
+following the password is ignored.
+
+<li>lib/config.cc: Added a new configuration item: postmaster.
+
+<li>commands/vadduser.cc (main): Removed the call to setup.
+
+<li>commands/vaddusers.cc (main): Removed the call to setup.
+
+<li>commands/vsetup.cc: Wrote this program to set up a new virtual
+domain with the proper ".qmail-default" file and a users
+directory, along with some useful system aliases.
+
+<li>daemon/vpwentry_cache.cc (write): Use "rename" system call.
+
+<li>lib/vpwentry_putpw.cc (putpw): Use "rename" sytem call.
+
+<li>lib/vpwentry_delpw.cc (delpw): Use "rename" system call instead
+of "unlink/link/unlink" combination to guarantee atomicity of the
+operation.
+
+<li>commands/_setup.cc (setup): Moved this routine out of
+vadduser.cc so that it could be shared with vaddusers.cc.  It
+should probably go into the shared library under a different
+name.
+
+<li>commands/vaddusers.cc: Wrote this new program that adds a list
+of users.  The input for this list is taken from standard input
+and is of the form "name password [alias ...]".
+
+<li>lib/vpwentry_putpw.cc (putpw): Fixed a bug in the logic that
+prevented the temporary password file from being renamed to a
+non-existant original file.
+
+</ul>
+</p>
+<p>1998-05-25  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.77
+
+<li>lib/vpwentry_putpw.cc (putpw): Fixed bug that would cause a
+failed addition to leave behind a temporary file as well as merged
+the case if the file does not already exist.
+
+</ul>
+</p>
+<p>1998-05-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/pwentry_cache.cc: Fixed this code to deal with shadow
+passwords.  Thanks to Andrew Gillespie for the initial patch to
+show the problems.  The new code properly deals with caching both
+the contents of /etc/shadow and /etc/passwd, as well as handling
+the case where shadow passwords don't exist.
+
+</ul>
+</p>
+<p>1998-05-22  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.76
+
+<li>daemon/file_cache.h (write_file): Call force_valid to avoid
+having to re-read the cached table immediately after having
+written its contents.  Do this _before_ unlocking the directory to
+avoid a race condition.
+
+<li>daemon/file_cache.cc (force_valid): Added this routine to force
+the cache state to indicate that the file is valid (if the file is
+present).
+
+</ul>
+</p>
+<p>1998-05-15  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/dispatch.cc (find_virtual): Fixed bug preventing use of
+wildcards in virtualdomains.
+
+</ul>
+</p>
+<p>1998-05-13  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/vpwentry_cache.cc (write): Set the new file mode to 0600.
+
+<li>lib/vpwentry_putpw.cc (putpw): Set the new file mode to 0600,
+not 0700 (no execute bit).
+
+</ul>
+</p>
+<p>1998-05-12  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/vpwentry_cache.cc (operator): Modified code to delete
+entries that fail insertion into the table (ie duplicates).
+
+<li>daemon/chpass.cc (CMD): Removed the calls to begin/end_modify.
+
+<li>daemon/file_cache.h (file_cache_writer::write_file): Removed the
+begin/end_modify routines and bundled them into this routine.
+
+</ul>
+</p>
+<p>1998-05-11  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/vpwentry_cache.cc (unlock): Fixed bug in unlocking the
+directory.
+
+<li>daemon/chpass.cc (CMD): Modified to use the file cache to modify
+the password table instead of the vuser_chpass routine.
+
+</ul>
+</p>
+<p>1998-05-08  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.75
+
+<li>daemon/main.cc (TIMEOUT): Changed the connection timeout to one
+second, as values larger than that are useful only for debugging
+the connection handling code.
+
+<li>lib/vpwentry_putpw.cc (putpw): Modified to use '\n' instead of
+the endl operator to mark line ends.
+
+<li>lib/vpwentry_delpw.cc (delpw): Modified to use '\n' instead of
+the endl operator to mark line ends (allows the output stream to
+properly buffer writes).
+
+</ul>
+</p>
+<p>1998-05-07  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>clients/checkvpw.cc, clients/vdeliver.cc: Moved these to files
+from "commands" to the "clients" subdirectory
+
+<li>daemon/pwentry_cache.cc (operator): Convert the user names to
+lowercase before inserting.
+
+<li>daemon/vpwentry_cache.cc (operator): Fixed bug: make the
+virtual users' names lowercase before inserting into the table.
+
+<li>daemon/check.cc (CMD): Fixed bug: initialize virtpw pointer.
+
+<li>daemon/lookup.cc (lookup_maildir): Removed obsolete routine.
+(CMD): Fixed bug: must initialize the pointers that previously
+used autodelete.
+
+<li>daemon/vpwentry_cache.cc (operator): Fixed a bug that caused the
+password and destination strings to be both stored in the password
+field.
+
+<li>daemon/file_cache.cc (validate_cache): Check both the last
+modification time on the file and the inode number to determine if
+the file has changed.
+
+<li>daemon/*.cc: Changed all variables of type "autodelete&lt;vpwentry&gt;"
+back to type "vpwentry*".
+
+<li>daemon/pwentry.cc: Removed the "getpw_byname" routine, now
+obsoleted by the pwentry_cache.
+
+<li>daemon/lookup.cc (lookup_virtuser): Modified to handle the new
+vpwtable cache in the pwentry.
+
+<li>daemon/pwentry.cc (pwentry): Initialize the vpwtable on
+creation.
+
+<li>daemon/pwentry.h (struct pwentry): Added a vpwentry_cache to
+this object.
+
+<li>daemon/vpwentry_cache.cc (write): Changed the end-of-line marker
+from endl to "\n", as endl will cause the buffer to be flushed.
+
+<li>daemon/main.cc (read_data): Removed support for protocol one
+requests (which allows me to remove one more read syscall from the
+fast path, shrinking it down to a total of two reads).
+
+</ul>
+</p>
+<p>1998-05-06  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/main.cc (read_data): Modified to read messages using
+either protocol one or two.
+
+<li>lib/server.cc (build_msg): Modified to build messages using
+protocol 2.
+
+<li>daemon/qmail.*: Removed these obsolete source files.
+
+<li>daemon/dispatch.cc (find_virtual): Wrote this routine that
+mimics the old behavior of find_virtual from qmail.cc to find a
+mapping from a virtual domain name to a prefix, using a map_cache
+on control/virtualdomains.
+
+<li>daemon/file_cache.h (class file_cache): Modified the behavior to
+automatically load the cache on construction, instead of waiting.
+
+<li>daemon/map_cache.h: Wrote the classes for map_cache, a generic
+qmail-style map-file cache (the key and value pair is separated by
+a colon, one per line).
+
+<li>daemon/list_cache.h: Renamed locals_cache to list_cache, as a
+generic list-file cache class.
+
+<li>daemon/dispatch.cc (is_local): Fixed to check the cached result.
+
+<li>daemon/file_cache.cc: Moved the actual code for file_cache_base
+here.
+
+<li>daemon/file_cache.h (class file_cache_base): Created this class
+to contain the common code in the file_cache template.
+
+<li>daemon/lookup.cc (lookup_baseuser): fixed the lookup to only
+read the cached "pwentries" object once per invocation, and to
+check the result.
+
+<li>daemon/qmail.cc (is_local): Removed this routine, as its
+functionality can be duplicated with a locals cache.
+
+<li>daemon/locals_cache.cc: Wrote this object to cache the "locals"
+table used by qmail to determine what domains are "local".
+
+<li>daemon/qmail.cc: Moved this object here from lib.
+
+<li>daemon/*.cc: Changed all variables of type "autodelete&lt;pwentry&gt;"
+back to type "pwentry*", as the lookup functions that would set
+these variables now return non-deletable references.
+
+<li>daemon/lookup.cc: Modified the various lookup routines that look
+up base users to use the pwentries cache.
+
+<li>daemon/file_cache.h:
+<li>daemon/hash_table.h:
+<li>daemon/crc32.h:
+<li>daemon/crc32.cc:
+<li>daemon/crc_hash.h:
+<li>daemon/pwentry_cache.cc:
+<li>daemon/pwentry_cache.h:
+<li>daemon/vpwentry_cache.cc:
+<li>daemon/vpwentry_cache.h: Merged from temporary development
+tree.  Current functionality consists of a generic hash table,
+mapping from mystring keys to generic objects; a file cache that
+will automatically reload a cached object only when necessary; and
+specific code for building caches of the base user password table
+(pwentry_cache) and virtual password tables (vpwentry_cache).
+
+<li>lib/vpwentry_putpw.cc (putpw): Now opens the temporary file with
+"noreplace" to avoid races, and mode 0700.
+
+<li>lib/vpwentry_delpw.cc (delpw): Now opens the temporary file with
+"noreplace" to avoid races, and mode 0700.
+
+</ul>
+</p>
+<p>1998-05-04  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/pwentry.*: Moved these files here from lib, as no other
+module uses them.
+
+<li>lib/pwentry.cc (getpw_byname): Moved this function here from
+pwentry_getpw.cc.
+
+<li>lib/vpwentry_delpw.cc: Renamed this file from pwentry_delpw.cc
+
+<li>lib/vpwentry_putpw.cc: Renamed this file from pwentry_putpw.cc
+
+<li>lib/vpwentry_getpw.cc: Added the getpw_byname function from
+pwentry_getpw.cc.
+
+<li>lib/pwentry_getpw.cc: Removed the vpwentry function.
+
+</ul>
+</p>
+<p>1998-05-03  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/vuser.h: Only include "vpwentry.h", not "pwentry.h"
+
+<li>lib/vpwentry.cc: Moved the vpwentry constructors and destructors
+here.
+
+<li>lib/pwentry.cc: Removed the vpwentry portions.
+
+<li>lib/pwentry.h: Removed the portions that only deal with
+vpwentry's.
+
+<li>lib/vpwentry.h: Split the portions of pwentry.h that only deal
+with vpwentry's into this file.
+
+<li>spec: Forgot to add a call to "ldconfig" in %post.
+
+</ul>
+</p>
+<p>1998-04-24  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.74.
+
+</ul>
+</p>
+<p>1998-04-23  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/chpass.cc (CMD): modified to use save_state.
+
+<li>daemon/deluser.cc (CMD): modified to use save_state.
+
+<li>daemon/delalias.cc (CMD): modified to use save_state.
+
+<li>daemon/addalias.cc (CMD): modified to use save_state and
+lookup_and_validate.
+
+<li>daemon/adduser.cc (CMD): Modified to use save_state.
+
+<li>daemon/state.h (class saved_state): Created this class from
+saved_uidgid -- it also does a chdir to the user's home
+directory.  By doing so, it allows the use of relative paths as if
+operating as the given user.
+
+<li>daemon/lookup.cc (lookup_and_validate): Modified to optionally
+create a new vpwentry if the named virtual shouldn't and doesn't
+exist yet.
+
+<li>daemon/adduser.cc (CMD): Modified to use lookup_and_validate and
+pwentry::user_dir_rel.
+
+<li>lib/pwentry.cc (user_dir_rel, user_dir_abs): Created these two
+routines that return the relative (to home) and absolute directory
+name of a new virtual user's directory according to the configured
+user_dir parameter.
+
+<li>commands/checkvpw.cc: Added function declarations missing on
+Solaris.
+
+<li>commands/vdeliver.cc: Added function declarations missing on
+Solaris.
+
+<li>lib/cgi-base.cc: Added function declarations missing on Solaris.
+
+<li>commands/vpasswd.cc: Added function declarations missing on
+Solaris.
+
+<li>commands/vadduser.cc: Added function declarations missing on
+Solaris.
+
+<li>lib/pwcrypt.cc: Added function declarations missing on Solaris.
+
+<li>daemon/dispatch.cc (dispatch_cmd): Add the domain name to the
+error message for an invalid domain name, as the request won't
+have been printed by the time this happens.
+
+</ul>
+</p>
+<p>1998-04-21  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vadduser.cc (add_alias): Fixed bug: this routine
+previously looked up the user name instead of the alias when
+checking for the existance of the alias.
+
+<li>lib/validate.cc (validate_field): Fixed bug: find_first returns
+-1 if nothing is found, not zero.
+
+<li>commands/vadduser.cc (add_alias): No longer necessary to add the
+'&' prefix.
+
+<li>commands/vaddalias.cc (main): No longer neccessary to add the
+'&' prefix.
+
+<li>lib/vuser_add.cc (vuser_addalias): Automatically prepend a '&'
+to the destination.
+
+<li>daemon/addalias.cc (CMD(addalias)): Call validate_redirect
+before adding the alias.
+
+</ul>
+</p>
+<p>1998-04-17  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vaddalias.cc (main): Removed the destination validation
+code from this program and made it call validate_redirect.
+
+<li>lib/validate.cc (validate_redirect): Created this routine to
+validate a redirect destination.
+
+</ul>
+</p>
+<p>1998-04-16  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/validate.cc (validate_username): Revised this to disallow
+'/' in user names.
+
+<li>vmailmgr.conf.sample: Added notes regarding which component(s)
+uses each of the listed settings.
+
+<li>lib/config.h: Removed the macro definitions that just served as
+aliases for parts of the configuration class.
+
+</ul>
+</p>
+<p>1998-04-14  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/lookup.cc: Removed the 'userlookup' routine.
+
+<li>lib/maildir.cc (make_maildir): Moved this routine here from
+vuser_add.
+(delete_maildir): Moved this routine here from vuser_deluser,
+renamed from deltree.
+
+</ul>
+</p>
+<p>1998-04-13  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/vuser_add.cc (vuser_add): Use validate routines instead of
+hard-coded checks.
+(vuser_adduser): Renamed the simple vuser_add to vuser_adduser to
+avoid confusion between the two vuser_add routines.
+
+<li>lib/validate.cc (validate_username): Wrote this routine to
+ensure that a username is valid; returns true if so.
+
+<li>daemon/delalias.cc (CMD(delalias)): Switched from userlookup to
+lookup_and_validate.
+
+<li>daemon/addalias.cc (CMD(addalias)): Switched from userlookup to
+lookup_{baseuser,virtuser}.  Removed check for invalid alias name
+(already done by vuser_addalias).
+
+<li>daemon/deluser.cc (CMD(deluser)): Switched from userlookup to
+lookup_and_validate.
+
+<li>daemon/adduser.cc (CMD(adduser)): Switched from userlookup to
+lookup_{baseuser,virtuser}.  Removed check for invalid user name
+(already done by vuser_add).  Removed duplicated code from
+vuser_adduser.
+
+<li>daemon/check.cc (CMD(check)): Switched from userlookup to
+lookup_{baseuser,virtuser}.
+
+<li>daemon/chpass.cc (CMD(chpass)): Switched from userlookup to
+lookup_and_validate.
+
+<li>daemon/lookup.cc (lookup_and_validate): Wrote this routine,
+which looks up base and virtual users and validates them,
+replacing several lines of common code in many of the interfaces.
+
+<li>commands/checkvpw.cc (main): Use the separators configuration
+item instead of just '@'.
+
+<li>lib/config.cc (read_config): Added a new configuration option,
+"separators", which lists valid separators between the user name
+and virtual domain name when logging in via checkvpw.  Defaults to
+"@:"
+
+<li>lib/mystring.cc (find_first): Added this routine, finds the
+first character that matches any one in a set.
+
+<li>daemon/lookup.cc (userlookup): Split this function into its two
+parts, lookup_baseuser and lookup_virtuser.
+
+</ul>
+</p>
+<p>1998-04-11  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vaddalias.cc (main): Modified this code to handle (and
+check) multiple recipients.
+
+<li>commands/vdeliver.cc (enqueue): Split this routine into three
+parts, and added the functionality to deal with multiple
+recipients in a destination address (separated by commas).
+
+</ul>
+</p>
+<p>1998-04-08  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>commands/vdeliver.cc (enqueue): Changed the calls to setenv to
+equivalent calls to putenv, as some system's don't have setenv.
+
+<li>commands/checkvpw.cc (set_environ): Changed the calls to setenv
+to equivalent calls to putenv, as some system's don't have setenv.
+
+</ul>
+</p>
+<p>1998-04-05  Bruce Guenter  &lt;bguenter@hal.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.73
+
+<li>commands/vdeliver.cc (main): Fixed bug with handling of ??LINE
+environment variables (local variables had erroneously overridden
+previously global variables).
+
+<li>vmailmgr-cgi.texi: Filled in the details for the form fields of
+vpasswd.
+
+<li>cgi/*.cc: Remove the "CGI_INPUT" lines for "vdomain" and
+"password", as they are defined by the top-level CGI constructor.
+
+<li>lib/cgi-base.cc (CGI): Add "vdomain" and "password" to the list
+of fields that are automatically retrieved for all the CGIs, as
+all CGIs will operate on a virtual domain, and all require a
+password.
+
+</ul>
+</p>
+<p>1998-04-02  Bruce Guenter  &lt;bguenter@hal.qcc.sk.ca&gt;
+<ul>
+
+<li>vmailmgr-cgi.texi: Started writing documentation on how to
+configure the CGI programs.
+
+</ul>
+</p>
+<p>1998-04-01  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>HOWTO.texi: Started writing instructions on how to do certain
+tasks with vmailmgr.
+
+</ul>
+</p>
+<p>1998-03-31  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/config.cc (read_config): Rewrote this routine to only go
+through the file once (instead of once per variable), and to print
+out errors on invalid lines.
+
+</ul>
+</p>
+<p>1998-03-29  Bruce Guenter  &lt;bguenter@hal.qcc.sk.ca&gt;
+<ul>
+
+<li>various: Use pwentry::pwfile and pwentry::user_dir in place of
+computing their values repeatedly.
+
+<li>lib/pwentry.cc (pwentry::pwfile): Wrote this routine, returns
+the password file name for the given base user.
+(pwentry::user_dir): Returns the user directory for the given base
+user.
+
+<li>lib/config.cc (post_process): Wrote this routine to "tidy up"
+some of the configuration strings, such as directories that should
+always have a trailing slash ('/').
+
+<li>lib/config.h: Change all the defined configuration macros
+(except for DO_SHADOW) to their configuration variables.
+
+<li>various: Treat the configuration defines as variables instead of
+as constant strings.
+
+<li>lib/config.cc (configuration): Initialize all the strings to
+default values.
+
+</ul>
+</p>
+<p>1998-03-28  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/config.cc: Started this module, which can read a
+configuration file for default values at runtime.  The default
+configuration initialization will read both a global configuration
+file and a local one.
+
+</ul>
+</p>
+<p>1998-03-26  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>Released version 0.72
+
+<li>commands/vdeliver.cc (main): Fixed the bug that caused empty
+environment variables (valid) to be treated as non-existant
+environment variables.  This caused bounces to vdeliver to double
+bounce.
+
+<li>Released version 0.71
+
+</ul>
+</p>
+<p>1998-03-22  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>cgi/*.cc: Use "msg", not "message()" from the response as the
+error response message.
+
+<li>lib/cgi-args.cc (get_parts): Strings weren't being terminated
+properly before being set.  Fixed.
+
+</ul>
+</p>
+<p>1998-03-20  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>daemon/dispatch.cc: Added entries for deluser, delalias, and
+addalias.
+
+<li>daemon/delalias.cc (CMD(delalias)): Wrote this routine to delete
+an alias.
+
+<li>daemon/addalias.cc (CMD(addalias)): Wrote this routine to add an
+alias.
+
+<li>cgi: Merged in all the code and libraries for CGI programs into
+the standard build.  At this point, there is a basic framework
+that all CGI programs will use, which includes a mechanism that
+automatically pulls the inputs from a POST form, and a base class
+that is executed on startup.  The CGI module defines the routine
+CGI_MAIN, which is executed by the program startup code.  The CGI
+module should call either error() or success() at the end of its
+execution, which will handle printing out an appropriate message.
+All of the v* programs (vpasswd, vadduser, vdeluser, vaddalias,
+and vdelalias) have a CGI equivalent.
+
+<li>daemon/deluser.cc (CMD(deluser)): Wrote this routine to delete a
+user.
+
+</ul>
+</p>
+<p>1998-03-19  Bruce Guenter  &lt;bguenter@mikhail.qcc.sk.ca&gt;
+<ul>
+
+<li>lib/server.cc: include un.h
+
+<li>daemon/main.cc: include un.h
+
+<li>lib/un.h: Wrote this header to define SUN_LEN and to include
+necessary things for doing sockets.
+
+<li>daemon/main.cc (make_socket): Split the code to create a socket
+into this routine; fixed the permissions bug that caused the
+socket to be created without other-write permission when launched
+with a non-zero umask.
+
+<li>Released version 0.70
+
+</ul>
+</p>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/FAQ.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,297 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+ <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
+ <TITLE>  VMailMgr FAQ</TITLE>
+
+
+</HEAD>
+<BODY>
+<H1>  VMailMgr FAQ</H1>
+
+<H2>Bruce Guenter 
+<A HREF="mailto:bruceg@em.ca">mailto:bruceg@em.ca</A>,
+  Dan Kuykendall 
+<A HREF="mailto:dan@kuykendall.org">mailto:dan@kuykendall.org</A></H2>  v1.0, 23 April 2000
+<P><HR>
+<EM>  VMailMgr Frequently Asked Questions.</EM>
+<HR>
+<H2><A NAME="s1">1. Building and Installing</A></H2>
+
+<H2>1.1 What compiler and libraries do I need to build vmailmgr?</H2>
+
+<P>You will need a working C and C++ compiler and linker. You will not
+need any C++ libraries.  The package is being developed under Linux
+using egcs and glibc version 2, and may rely on some gcc/g++
+extensions.
+<H2>1.2 Does vmailmgr work with shadow passwords?</H2>
+
+<P>This package should work without changes both with and without
+shadow passwords as long as the shadow password libraries are
+present when this package is built. The `configure' script will
+detect what method of shadow passwords are being used and the
+programs will be built accordingly.
+<H2>1.3 Does vmailmgr support IMAP?</H2>
+
+<P>Yes, vmailmgr supports Courier-IMAP.  Some minor steps are needed to
+make them work, the steps are in the next section of this file.
+<H2><A NAME="s2">2. Setup and Configuration</A></H2>
+
+<H2>2.1 What other software is needed to run vmailmgr?</H2>
+
+<P>VMailMgr is based around qmail's handling of virtual users, and as
+such requires qmail for its operation. If you wish to use the `init'
+file to start/stop vmailmgrd or are installing the RPM package,
+supervise-scripts version 2.2 (or later, available at 
+<A HREF="http://em.ca/~bruceg/supervise-scripts/">http://em.ca/~bruceg/supervise-scripts/</A>) and daemontools 0.60
+(or later, available at 
+<A HREF="http://em.ca/~bruceg/rpms/daemontools/">http://em.ca/~bruceg/rpms/daemontools/</A>) packages are
+required.  If you need to use the <CODE>vmailmgrd</CODE> daemon, you
+will also need the <CODE>unixserver</CODE> program, from the ucspi-unix
+package, available at 
+<A HREF="http://em.ca/~bruceg/ucspi-unix/">http://em.ca/~bruceg/ucspi-unix/</A>.
+<P>If you want to use the autoresponse feature, I recommend the use of
+my own autoresponder program, <CODE>qmail-autoresponder</CODE> available
+at 
+<A HREF="http://em.ca/~bruceg/qmail-autoresponder/">http://em.ca/~bruceg/qmail-autoresponder/</A>.
+<H2>2.2 How do I record the output of vmailmgrd with syslog?</H2>
+
+<P>Output from vmailmgrd can be recorded by either splogger (part of
+qmail) or with the logger that comes with several flavours of
+UNIX. To use splogger, pipe the output of vmailmgrd into the command
+`splogger vmailmgrd'. This will timestamp each entry and tag them
+with the word `vmailmgrd'. By default, splogger logs to facility 2
+(mail). To use logger, pipe the output of vmailmgrd into the
+comamand `<CODE>logger -t vmailmgrd -p mail.notice</CODE>'. See the
+respective man pages of these two programs for more information.
+<P>Note: The use of syslog for logging messages is strongly discouraged
+due to problems with inefficent and buggy implementation of syslog.
+<H2>2.3 How do I record the output of vmailmgrd with multilog?</H2>
+
+<P>Make a directory into which the output will go, for example
+`<CODE>/var/log/vmailmgrd</CODE>'. Pipe the output of vmailmgrd into the
+command `<CODE>multilog t /var/log/vmailmgrd</CODE>'. See the
+documentation for multilog for more information on how to adjust its
+output.
+<H2>2.4 How do I setup VMmailMgr IMAP support?</H2>
+
+<P>VMailMgr supports Courier-IMAP, but Courier-IMAP does not auto
+detect VMailMgr.  This means that some minor work is required for
+making the two work together.
+<UL>
+<LI>You must copy `<CODE>/usr/local/bin/authvmailmgr</CODE>` to
+`<CODE>/usr/lib/courier-imap/libexec/authlib/authvmailmgr</CODE>`.</LI>
+<LI>Then modify the `<CODE>AUTHMODULES</CODE>` statement in
+`<CODE>/usr/lib/courier-imap/etc/imapd.config</CODE>` and add
+`<CODE>authvmailmgr</CODE>` as the first authentication module.</LI>
+</UL>
+<H2>2.5 Upgrading from Previous Versions</H2>
+
+<P>If you are upgrading from an older version, you may need to make
+some changes to your system before or after doing the upgrade. The
+following table outlines the necessary changes. Note that you need
+to follow the instructions for all later versions of the software.
+<P>If you are upgrading from version: 
+<DL>
+<DT><B>0.96.6 or earlier</B><DD><P>The `vmailmgrd' daemon needs to be run by unixserver, as opposed
+to being a stand-alone program previously.
+<DT><B>0.96.2 or earlier</B><DD><P>Make sure the `vmailmgrd' daemon and vmailmgr CGIs are disabled
+before upgrading, and upgrade them along with the main
+package. Changes were made to the daemon interface that will
+cause adding users and aliases to flake out. As well, the
+listdomain interface was completely redone.
+<P>
+<DT><B>0.94 or earlier, using the POP bulletin facility</B><DD><P>The POP bulletin facility has been moved into a stand-alone
+program that needs to be executed through `checkvpw-postsetuid'.
+<P>
+<DT><B>0.93 or earlier</B><DD><P>If you do not use the CGIs, you no longer need to run the
+`vmailmgrd' daemon.
+<P>
+<DT><B>0.92.2 or earlier</B><DD><P>The configuration changed from reading a single file to reading a
+set of files in a directory. Read the configuration documentation
+and run the program `vconf2dir'.
+<P>
+<DT><B>0.90.2 or earlier</B><DD><P>The name of the user to which mail to an unknown user is
+delivered changed from `*' to `+'. If you were using this
+feature, either change all your domains to accomodate this
+change, or set the `default-username' config file to contain `*'.
+<P>
+<DT><B>0.88 or earlier</B><DD><P>The file format of the virtual password tables has changed from
+plain text files to CDB tables. You will need to suspend local
+deliveries before upgrading, and run the program `vpasswd2cdb' as
+each base user after upgrading, before re-enabling local
+deliveries.
+</DL>
+<H2>2.6 How do I configure qmail+patches to use vmailmgr for POP?</H2>
+
+<P>Put the string `<CODE>checkvpw</CODE>' into the file
+`<CODE>/etc/qmail/control/checkpassword</CODE>' and restart pop3d by
+typing `<CODE>/etc/rc.d/init.d/pop3d restart</CODE>'.
+<H2>2.7 How do I allow clients to relay SMTP through me?</H2>
+
+<P>Download and install relay-ctrl from 
+<A HREF="http://em.ca/~bruceg/relay-ctrl/">http://em.ca/~bruceg/relay-ctrl/</A>.
+It works with vmailmgr, for both POP3 and IMAP clients.
+<H2><A NAME="s3">3. Usage</A></H2>
+
+<H2>3.1 I can only use one IP address. How do I log in as a virtual user?</H2>
+
+<P>There are two ways to log in without using multiple IP addresses.
+<P>The first way is to log in as `userSEPvirtual.domain.org', where
+`user' is the mailbox name of the virtual user, SEP is one of `@' or
+`:' (by default, this is configurable in the
+`<CODE>/etc/vmailmgr/</CODE>' directory), and
+`<CODE>virtual.domain.org</CODE>' is the virtual domain's name, as
+listed in `<CODE>/var/qmail/control/virtualdomains</CODE>'.
+<P>The second way is to use the internal form of the mailbox name --
+that is, `<CODE>baseuser-user</CODE>', where `<CODE>user</CODE>' is the same
+as above, and `<CODE>baseuser</CODE>' is the username of the managing
+user.
+<P>Example: `<CODE>/var/qmail/control/virtualdomains</CODE>' contains 
+<PRE>
+  testdomain.org:testuser
+</PRE>
+
+User `<CODE>testuser</CODE>' exists, and has set up a virtual mailbox
+with the name `<CODE>v</CODE>'. The `<CODE>separators</CODE>' variable in
+`<CODE>/etc/vmailmgr/</CODE>' contains `<CODE>@:</CODE>'. This virtual user
+could log in as `<CODE>v@testdomain.org</CODE>',
+`<CODE>v:testdomain.org</CODE>', or `<CODE>testuser-v</CODE>'.
+<P>
+<P>
+<H2>3.2 How do I get all misdirected mail sent to me?</H2>
+
+<P>In the `<CODE>vmailmgr/</CODE>' configuration directory, there is an
+entry called `<CODE>default-username</CODE>'. If mail to a virtual
+domain does not match any users or aliases in that domain, it is
+delivered to the name listed in this configuration item if it exists
+(which defaults to `<CODE>+</CODE>'). To make this deliver to you,
+simply type:
+<PRE>
+  vaddalias + me
+</PRE>
+<H2><A NAME="s4">4. Troubleshooting</A></H2>
+
+<H2>4.1 Bind error message from vmailmgrd.</H2>
+
+<P>If vmailmgrd reports `<CODE>vmailmgrd: bind: no such file or
+directory</CODE>' when you start it up, it means that can't create its
+socket file.  By default, it will try to create the socket file
+`<CODE>/tmp/.vmailmgrd</CODE>'. You must ensure that `<CODE>/tmp</CODE>' is
+writable, or that the socket is created in some other place by
+setting `<CODE>socket-file</CODE>' in the configuration.
+<H2>4.2 Error sending to an alias: qmail-queue exited with an error!</H2>
+
+<P>If qmail reports "deferral: vdeliver: qmail-queue exited with an
+error!", check where your qmail is installed.  On Debian systems,
+you will need to type "<CODE>ls -s /usr/sbin /var/qmail/bin</CODE>",
+since they've installed the qmail binaries into /usr/sbin.
+<H2>4.3 Running vmailmgrd fails.</H2>
+
+<P>When run by itself, vmailmgrd will report "<CODE>Timed out waiting for
+remote</CODE>".  vmailmgrd needs to be run from unixserver, part of
+the ucspi-unix package available at 
+<A HREF="http://em.ca/~bruceg/ucspi-unix/">http://em.ca/~bruceg/ucspi-unix/</A>.
+<H2>4.4 POP3 or IMAP logins take 30 seconds or longer.</H2>
+
+<P>This is almost certainly a DNS lookup problem.  Make sure that DNS
+lookups aren't timing out, that lookups on all your IP addresses
+aren't failing, and that you can lookup remote addresses as well.
+<P>If you are using 'tcpserver' for the head end to qmail-pop3d, then you
+may want to the following 2 switches to the command line: <CODE>-R</CODE>
+and <CODE>-H</CODE>.  The former prevents tcpserver from attempting to
+obtain TCPREMOTEINFO from the remote host.  This eliminates an "ident"
+lookup that may be being blocked or silently dropped by a firewall.
+The latter prevents tcpserver from doing a DNS lookup on the remote
+IP.
+<H2><A NAME="s5">5. Miscellaneous</A></H2>
+
+<H2>5.1 How do I get in contact with other users?</H2>
+
+<P>There is a mailing list run by the author. To subscribe, send an
+e-mail (content and subject line is ignored) to 
+<A HREF="mailto:vmailmgr-subscribe@lists.em.ca">mailto:vmailmgr-subscribe@lists.em.ca</A>.
+<P>Remember that if you have a problem that you want us to diagnose, we
+need to know the following important details:
+<OL>
+<LI>The output of `<CODE>qmail-showctl</CODE>` </LI>
+<LI>The contents of the vmailmgrd log for the attempt you are
+trying to diagnose</LI>
+<LI>The contents of the qmail and smtpd logs for a failed delivery
+attempt</LI>
+<LI>The contents of the pop3d logs for a failed login attempt</LI>
+<LI>The complete command line with which vmailmgrd and qmail-pop3d
+was invoked</LI>
+</OL>
+
+Please do not contact the author directly with vmailmgr questions. 
+<H2>5.2 Are development version of vmailmgr available anywhere?</H2>
+
+<P>Yes, they are available through anonymous CVS.
+To access the CVS server, set your <CODE>CVSROOT</CODE> to
+<CODE>:pserver:cvs@bruce-guenter.dyndns.org:/CVS</CODE>, log in with an
+empty password, and check out the <CODE>vmailmgr</CODE> module.
+<H2>5.3 How does incoming email get handled?</H2>
+
+<P>Incoming email is first received by the qmail SMTP daemon and
+inserted into the qmail queue. Then `<CODE>qmail-send</CODE>' examines
+the email envelope (which details the recipient address or
+addresses) to determine how to dispatch the message. It looks up the
+domain name of each recipient in
+`<CODE>/var/qmail/control/virtualdomains</CODE>', and prefixes the user
+name with the string that it finds. It then looks up the resulting
+user name in the system password table (or in
+`<CODE>/var/qmail/users/cdb</CODE>' if it exists) to find the base user
+name and home directory (which I will call `<CODE>$HOME</CODE>'). It
+then looks for the file `<CODE>$HOME/.qmail-VIRTUAL</CODE>'. If that's
+not found, it looks for the file `<CODE>$HOME/.qmail-default</CODE>',
+which will contain an instruction to pipe the message to
+`<CODE>vdeliver</CODE>'.
+<P>This is where vmailmgr first enters the picture. The virtual user
+name is sent to `vdeliver' through environment variables. It looks
+in the configuration files (in `<CODE>$HOME/.vmailmgr</CODE>' and then
+in `<CODE>/etc/vmailmgr</CODE>') to determine the location of the
+password table, and looks up the virtual user name in the table to
+determine delivery instructions. If the name is not found, the
+message is bounced and delivery ends. Otherwise, it then looks for
+the `<CODE>vdeliver-predeliver</CODE>' script in the configuration
+directories (in reverse order) and executes any that are found. It
+then delivers the message to all the listed destinations -- an
+optional mailbox directory and zero or more forwarding
+addresses. Finally, it looks for the `<CODE>vdeliver-postdeliver</CODE>'
+script and executes any that are found.
+<H2>5.4 How does outgoing email get handled?</H2>
+
+<P>Outgoing email is not handled by vmailmgr. For details on outgoing
+email handling, check the qmail documentation.
+<H2>5.5 What about security of CGI and PHP functions?</H2>
+
+<P>The socket used by the daemon is a UNIX-domain socket (as opposed to
+Internet-domain), meaning you need local access on the computer to
+open up a connection.  The path for this socket is run-time
+configurable.
+<P>The daemon forks a new connection for each connection, up to a
+configurable maximum (at which point it stops listening, IIRC, I
+should verify this).  The idea of threading has been completely
+discarded to avoid a bug in a command creeping in and makeing the
+whole server break.
+<P>The protocol spoken over the socket is explicitly bounded to at most
+64kB of data, and all data is prefixed by a size.  Static-sized
+buffers are only used with static-sized reads, and therefore can't be
+overflowed with stack-smashing tricks.
+<P>The daemon commands setuid to the appropriate user as soon as the base
+user has been verified, to avoid doing any more than necessary as
+root, as well as to avoid the possibility of tricking the daemon into
+reading a file another user wouldn't normally have access to.
+<P>To help avoid DoS on the local computer, a 1-second alarm is set as
+soon as the connection is received, and is only cleared once all the
+data has been read.  If it takes longer than 1 second to read the data
+from the socket, the server process exits.
+<H2>5.6 What are the differences between vmailmgr and vpopmail?</H2>
+
+<P>The primary difference between vmailmgr and vpopmail is the use of
+base users.  With vmailmgr there is one base user for each virtual
+domain.  With vpopmail, there is one base user for the entire
+virtual domain system.
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/FAQ.sgml	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,373 @@
+<!doctype linuxdoc system>
+
+<!-- LinuxDoc file was created by hand by <Dan Kuykendall> Wed April 23 -->
+<article>
+<title>
+  VMailMgr FAQ
+</title>
+<author>
+  Bruce Guenter <url url="mailto:bruceg@em.ca">,
+  Dan Kuykendall <url url="mailto:dan@kuykendall.org">
+</author>
+<date>
+  v1.0, 23 April 2000
+</date>
+<abstract>
+  VMailMgr Frequently Asked Questions.
+</abstract>
+
+<toc>
+
+<sect>Building and Installing
+
+<sect1>What compiler and libraries do I need to build vmailmgr?
+<p>
+  You will need a working C and C++ compiler and linker. You will not
+  need any C++ libraries.  The package is being developed under Linux
+  using egcs and glibc version 2, and may rely on some gcc/g++
+  extensions.
+</p>
+
+<sect1>Does vmailmgr work with shadow passwords?
+<p>
+  This package should work without changes both with and without
+  shadow passwords as long as the shadow password libraries are
+  present when this package is built. The `configure' script will
+  detect what method of shadow passwords are being used and the
+  programs will be built accordingly.
+</p>
+
+<sect1>Does vmailmgr support IMAP?
+<p>
+  Yes, vmailmgr supports Courier-IMAP.  Some minor steps are needed to
+  make them work, the steps are in the next section of this file.
+</p>
+
+<sect>Setup and Configuration
+
+<sect1>What other software is needed to run vmailmgr?
+<p>
+  VMailMgr is based around qmail's handling of virtual users, and as
+  such requires qmail for its operation. If you wish to use the `init'
+  file to start/stop vmailmgrd or are installing the RPM package,
+  supervise-scripts version 2.2 (or later, available at <url
+  url="http://em.ca/~bruceg/supervise-scripts/">) and daemontools 0.60
+  (or later, available at <url
+  url="http://em.ca/~bruceg/rpms/daemontools/">) packages are
+  required.  If you need to use the <tt>vmailmgrd</tt> daemon, you
+  will also need the <tt>unixserver</tt> program, from the ucspi-unix
+  package, available at <url url="http://em.ca/~bruceg/ucspi-unix/">.
+</p>
+
+<p>
+  If you want to use the autoresponse feature, I recommend the use of
+  my own autoresponder program, <tt>qmail-autoresponder</tt> available
+  at <url url="http://em.ca/~bruceg/qmail-autoresponder/">.
+</p>
+
+<sect1>How do I record the output of vmailmgrd with syslog?
+<p>
+  Output from vmailmgrd can be recorded by either splogger (part of
+  qmail) or with the logger that comes with several flavours of
+  UNIX. To use splogger, pipe the output of vmailmgrd into the command
+  `splogger vmailmgrd'. This will timestamp each entry and tag them
+  with the word `vmailmgrd'. By default, splogger logs to facility 2
+  (mail). To use logger, pipe the output of vmailmgrd into the
+  comamand `<tt>logger -t vmailmgrd -p mail.notice</tt>'. See the
+  respective man pages of these two programs for more information.
+</p>
+<p>
+  Note: The use of syslog for logging messages is strongly discouraged
+  due to problems with inefficent and buggy implementation of syslog.
+</p>
+
+<sect1>How do I record the output of vmailmgrd with multilog?
+<p>
+  Make a directory into which the output will go, for example
+  `<tt>/var/log/vmailmgrd</tt>'. Pipe the output of vmailmgrd into the
+  command `<tt>multilog t /var/log/vmailmgrd</tt>'. See the
+  documentation for multilog for more information on how to adjust its
+  output.
+</p>
+
+<sect1>How do I setup VMmailMgr IMAP support?
+<p>
+  VMailMgr supports Courier-IMAP, but Courier-IMAP does not auto
+  detect VMailMgr.  This means that some minor work is required for
+  making the two work together.
+<itemize>
+  <item>You must copy `<tt>/usr/local/bin/authvmailmgr</tt>` to
+        `<tt>/usr/lib/courier-imap/libexec/authlib/authvmailmgr</tt>`.
+  <item>Then modify the `<tt>AUTHMODULES</tt>` statement in
+        `<tt>/usr/lib/courier-imap/etc/imapd.config</tt>` and add
+        `<tt>authvmailmgr</tt>` as the first authentication module.
+</itemize>
+</p>
+
+<sect1>Upgrading from Previous Versions
+<p>
+  If you are upgrading from an older version, you may need to make
+  some changes to your system before or after doing the upgrade. The
+  following table outlines the necessary changes. Note that you need
+  to follow the instructions for all later versions of the software.
+<p>
+  If you are upgrading from version: 
+<descrip>
+<tag>0.96.6 or earlier</tag>
+<p>
+    The `vmailmgrd' daemon needs to be run by unixserver, as opposed
+    to being a stand-alone program previously.
+</p>
+<tag>0.96.2 or earlier</tag>
+<p>
+     Make sure the `vmailmgrd' daemon and vmailmgr CGIs are disabled
+     before upgrading, and upgrade them along with the main
+     package. Changes were made to the daemon interface that will
+     cause adding users and aliases to flake out. As well, the
+     listdomain interface was completely redone.
+<p>
+<tag>0.94 or earlier, using the POP bulletin facility</tag>
+<p>
+     The POP bulletin facility has been moved into a stand-alone
+     program that needs to be executed through `checkvpw-postsetuid'.
+<p>
+<tag>0.93 or earlier</tag>
+<p>
+     If you do not use the CGIs, you no longer need to run the
+     `vmailmgrd' daemon.
+<p>
+<tag>0.92.2 or earlier</tag>
+<p>
+     The configuration changed from reading a single file to reading a
+     set of files in a directory. Read the configuration documentation
+     and run the program `vconf2dir'.
+<p>
+<tag>0.90.2 or earlier</tag>
+<p>
+     The name of the user to which mail to an unknown user is
+     delivered changed from `*' to `+'. If you were using this
+     feature, either change all your domains to accomodate this
+     change, or set the `default-username' config file to contain `*'.
+<p>
+<tag>0.88 or earlier</tag>
+<p>
+     The file format of the virtual password tables has changed from
+     plain text files to CDB tables. You will need to suspend local
+     deliveries before upgrading, and run the program `vpasswd2cdb' as
+     each base user after upgrading, before re-enabling local
+     deliveries.
+</descrip>
+</p>
+
+<sect1>How do I configure qmail+patches to use vmailmgr for POP?
+<p>
+Put the string `<tt>checkvpw</tt>' into the file
+`<tt>/etc/qmail/control/checkpassword</tt>' and restart pop3d by
+typing `<tt>/etc/rc.d/init.d/pop3d restart</tt>'.
+</p>
+
+<sect1>How do I allow clients to relay SMTP through me?
+<p>
+  Download and install relay-ctrl from <url
+  url="http://em.ca/~bruceg/relay-ctrl/">.
+  It works with vmailmgr, for both POP3 and IMAP clients.
+</p>
+
+<sect>Usage
+
+<sect1>I can only use one IP address. How do I log in as a virtual user?
+<p>
+  There are two ways to log in without using multiple IP addresses.
+<p>
+  The first way is to log in as `userSEPvirtual.domain.org', where
+  `user' is the mailbox name of the virtual user, SEP is one of `@' or
+  `:' (by default, this is configurable in the
+  `<tt>/etc/vmailmgr/</tt>' directory), and
+  `<tt>virtual.domain.org</tt>' is the virtual domain's name, as
+  listed in `<tt>/var/qmail/control/virtualdomains</tt>'.
+<p>
+  The second way is to use the internal form of the mailbox name --
+  that is, `<tt>baseuser-user</tt>', where `<tt>user</tt>' is the same
+  as above, and `<tt>baseuser</tt>' is the username of the managing
+  user.
+
+  Example: `<tt>/var/qmail/control/virtualdomains</tt>' contains 
+<verb>
+  testdomain.org:testuser
+</verb>
+  User `<tt>testuser</tt>' exists, and has set up a virtual mailbox
+  with the name `<tt>v</tt>'. The `<tt>separators</tt>' variable in
+  `<tt>/etc/vmailmgr/</tt>' contains `<tt>@:</tt>'. This virtual user
+  could log in as `<tt>v@testdomain.org</tt>',
+  `<tt>v:testdomain.org</tt>', or `<tt>testuser-v</tt>'.
+<p>
+
+<sect1>How do I get all misdirected mail sent to me?
+<p>
+  In the `<tt>vmailmgr/</tt>' configuration directory, there is an
+  entry called `<tt>default-username</tt>'. If mail to a virtual
+  domain does not match any users or aliases in that domain, it is
+  delivered to the name listed in this configuration item if it exists
+  (which defaults to `<tt>+</tt>'). To make this deliver to you,
+  simply type:
+<verb>
+  vaddalias + me
+</verb>
+</p>
+
+<sect>Troubleshooting
+
+<sect1>Bind error message from vmailmgrd.
+<p>
+  If vmailmgrd reports `<tt>vmailmgrd: bind: no such file or
+  directory</tt>' when you start it up, it means that can't create its
+  socket file.  By default, it will try to create the socket file
+  `<tt>/tmp/.vmailmgrd</tt>'. You must ensure that `<tt>/tmp</tt>' is
+  writable, or that the socket is created in some other place by
+  setting `<tt>socket-file</tt>' in the configuration.
+</p>
+
+<sect1>Error sending to an alias: qmail-queue exited with an error!
+<p>
+  If qmail reports "deferral: vdeliver: qmail-queue exited with an
+  error!", check where your qmail is installed.  On Debian systems,
+  you will need to type "<tt>ls -s /usr/sbin /var/qmail/bin</tt>",
+  since they've installed the qmail binaries into /usr/sbin.
+</p>
+
+<sect1>Running vmailmgrd fails.
+<p>
+  When run by itself, vmailmgrd will report "<tt>Timed out waiting for
+  remote</tt>".  vmailmgrd needs to be run from unixserver, part of
+  the ucspi-unix package available at <url
+  url="http://em.ca/~bruceg/ucspi-unix/">.
+</p>
+
+<sect1>POP3 or IMAP logins take 30 seconds or longer.
+<p>
+  This is almost certainly a DNS lookup problem.  Make sure that DNS
+  lookups aren't timing out, that lookups on all your IP addresses
+  aren't failing, and that you can lookup remote addresses as well.
+</p>
+
+<p>
+  If you are using 'tcpserver' for the head end to qmail-pop3d, then you
+  may want to the following 2 switches to the command line: <tt>-R</tt>
+  and <tt>-H</tt>.  The former prevents tcpserver from attempting to
+  obtain TCPREMOTEINFO from the remote host.  This eliminates an "ident"
+  lookup that may be being blocked or silently dropped by a firewall.
+  The latter prevents tcpserver from doing a DNS lookup on the remote
+  IP.
+</p>
+
+<sect>Miscellaneous
+
+<sect1>How do I get in contact with other users?
+<p>
+  There is a mailing list run by the author. To subscribe, send an
+  e-mail (content and subject line is ignored) to <url
+  url="mailto:vmailmgr-subscribe@lists.em.ca">.
+<p>
+  Remember that if you have a problem that you want us to diagnose, we
+  need to know the following important details:
+<enum>
+  <item>The output of `<tt>qmail-showctl</tt>` 
+  <item>The contents of the vmailmgrd log for the attempt you are
+  trying to diagnose
+  <item>The contents of the qmail and smtpd logs for a failed delivery
+  attempt
+  <item>The contents of the pop3d logs for a failed login attempt
+  <item>The complete command line with which vmailmgrd and qmail-pop3d
+  was invoked
+</enum>
+  Please do not contact the author directly with vmailmgr questions. 
+</p>
+
+<sect1>Are development version of vmailmgr available anywhere?
+<p>
+  Yes, they are available through anonymous CVS.
+  To access the CVS server, set your <tt>CVSROOT</tt> to
+  <tt>:pserver:cvs@bruce-guenter.dyndns.org:/CVS</tt>, log in with an
+  empty password, and check out the <tt>vmailmgr</tt> module.
+</p>
+
+<sect1>How does incoming email get handled?
+<p>
+  Incoming email is first received by the qmail SMTP daemon and
+  inserted into the qmail queue. Then `<tt>qmail-send</tt>' examines
+  the email envelope (which details the recipient address or
+  addresses) to determine how to dispatch the message. It looks up the
+  domain name of each recipient in
+  `<tt>/var/qmail/control/virtualdomains</tt>', and prefixes the user
+  name with the string that it finds. It then looks up the resulting
+  user name in the system password table (or in
+  `<tt>/var/qmail/users/cdb</tt>' if it exists) to find the base user
+  name and home directory (which I will call `<tt>$HOME</tt>'). It
+  then looks for the file `<tt>$HOME/.qmail-VIRTUAL</tt>'. If that's
+  not found, it looks for the file `<tt>$HOME/.qmail-default</tt>',
+  which will contain an instruction to pipe the message to
+  `<tt>vdeliver</tt>'.
+<p>
+  This is where vmailmgr first enters the picture. The virtual user
+  name is sent to `vdeliver' through environment variables. It looks
+  in the configuration files (in `<tt>$HOME/.vmailmgr</tt>' and then
+  in `<tt>/etc/vmailmgr</tt>') to determine the location of the
+  password table, and looks up the virtual user name in the table to
+  determine delivery instructions. If the name is not found, the
+  message is bounced and delivery ends. Otherwise, it then looks for
+  the `<tt>vdeliver-predeliver</tt>' script in the configuration
+  directories (in reverse order) and executes any that are found. It
+  then delivers the message to all the listed destinations -- an
+  optional mailbox directory and zero or more forwarding
+  addresses. Finally, it looks for the `<tt>vdeliver-postdeliver</tt>'
+  script and executes any that are found.
+</p>
+
+<sect1>How does outgoing email get handled?
+<p>
+  Outgoing email is not handled by vmailmgr. For details on outgoing
+  email handling, check the qmail documentation.
+</p>
+
+<sect1>What about security of CGI and PHP functions?
+<p>
+The socket used by the daemon is a UNIX-domain socket (as opposed to
+Internet-domain), meaning you need local access on the computer to
+open up a connection.  The path for this socket is run-time
+configurable.
+</p>
+<p>
+The daemon forks a new connection for each connection, up to a
+configurable maximum (at which point it stops listening, IIRC, I
+should verify this).  The idea of threading has been completely
+discarded to avoid a bug in a command creeping in and makeing the
+whole server break.
+</p>
+<p>
+The protocol spoken over the socket is explicitly bounded to at most
+64kB of data, and all data is prefixed by a size.  Static-sized
+buffers are only used with static-sized reads, and therefore can't be
+overflowed with stack-smashing tricks.
+</p>
+<p>
+The daemon commands setuid to the appropriate user as soon as the base
+user has been verified, to avoid doing any more than necessary as
+root, as well as to avoid the possibility of tricking the daemon into
+reading a file another user wouldn't normally have access to.
+</p>
+<p>
+To help avoid DoS on the local computer, a 1-second alarm is set as
+soon as the connection is received, and is only cleared once all the
+data has been read.  If it takes longer than 1 second to read the data
+from the socket, the server process exits.
+</p>
+
+<sect1>What are the differences between vmailmgr and vpopmail?
+<p>
+  The primary difference between vmailmgr and vpopmail is the use of
+  base users.  With vmailmgr there is one base user for each virtual
+  domain.  With vpopmail, there is one base user for the entire
+  virtual domain system.
+</p>
+
+</article>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/FAQ.txt	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,396 @@
+  VMailMgr FAQ
+  Bruce Guenter  <mailto:bruceg@em.ca>, Dan Kuykendall
+  <mailto:dan@kuykendall.org>
+  v1.0, 23 April 2000
+
+  VMailMgr Frequently Asked Questions.
+  ______________________________________________________________________
+
+  Table of Contents
+
+
+  1. Building and Installing
+
+     1.1 What compiler and libraries do I need to build vmailmgr?
+     1.2 Does vmailmgr work with shadow passwords?
+     1.3 Does vmailmgr support IMAP?
+
+  2. Setup and Configuration
+
+     2.1 What other software is needed to run vmailmgr?
+     2.2 How do I record the output of vmailmgrd with syslog?
+     2.3 How do I record the output of vmailmgrd with multilog?
+     2.4 How do I setup VMmailMgr IMAP support?
+     2.5 Upgrading from Previous Versions
+     2.6 How do I configure qmail+patches to use vmailmgr for POP?
+     2.7 How do I allow clients to relay SMTP through me?
+
+  3. Usage
+
+     3.1 I can only use one IP address. How do I log in as a virtual user?
+     3.2 How do I get all misdirected mail sent to me?
+
+  4. Troubleshooting
+
+     4.1 Bind error message from vmailmgrd.
+     4.2 Error sending to an alias: qmail-queue exited with an error!
+     4.3 Running vmailmgrd fails.
+     4.4 POP3 or IMAP logins take 30 seconds or longer.
+
+  5. Miscellaneous
+
+     5.1 How do I get in contact with other users?
+     5.2 Are development version of vmailmgr available anywhere?
+     5.3 How does incoming email get handled?
+     5.4 How does outgoing email get handled?
+     5.5 What about security of CGI and PHP functions?
+     5.6 What are the differences between vmailmgr and vpopmail?
+
+
+  ______________________________________________________________________
+
+  11..  BBuuiillddiinngg aanndd IInnssttaalllliinngg
+
+  11..11..  WWhhaatt ccoommppiilleerr aanndd lliibbrraarriieess ddoo II nneeeedd ttoo bbuuiilldd vvmmaaiillmmggrr??
+
+  You will need a working C and C++ compiler and linker. You will not
+  need any C++ libraries.  The package is being developed under Linux
+  using egcs and glibc version 2, and may rely on some gcc/g++
+  extensions.
+
+  11..22..  DDooeess vvmmaaiillmmggrr wwoorrkk wwiitthh sshhaaddooww ppaasssswwoorrddss??
+
+  This package should work without changes both with and without shadow
+  passwords as long as the shadow password libraries are present when
+  this package is built. The `configure' script will detect what method
+  of shadow passwords are being used and the programs will be built
+  accordingly.
+
+  11..33..  DDooeess vvmmaaiillmmggrr ssuuppppoorrtt IIMMAAPP??
+
+  Yes, vmailmgr supports Courier-IMAP.  Some minor steps are needed to
+  make them work, the steps are in the next section of this file.
+
+  22..  SSeettuupp aanndd CCoonnffiigguurraattiioonn
+
+  22..11..  WWhhaatt ootthheerr ssooffttwwaarree iiss nneeeeddeedd ttoo rruunn vvmmaaiillmmggrr??
+
+  VMailMgr is based around qmail's handling of virtual users, and as
+  such requires qmail for its operation. If you wish to use the `init'
+  file to start/stop vmailmgrd or are installing the RPM package,
+  supervise-scripts version 2.2 (or later, available at
+  <http://em.ca/~bruceg/supervise-scripts/>) and daemontools 0.60 (or
+  later, available at  <http://em.ca/~bruceg/rpms/daemontools/>)
+  packages are required.  If you need to use the vmailmgrd daemon, you
+  will also need the unixserver program, from the ucspi-unix package,
+  available at  <http://em.ca/~bruceg/ucspi-unix/>.
+
+  If you want to use the autoresponse feature, I recommend the use of my
+  own autoresponder program, qmail-autoresponder available at
+  <http://em.ca/~bruceg/qmail-autoresponder/>.
+
+  22..22..  HHooww ddoo II rreeccoorrdd tthhee oouuttppuutt ooff vvmmaaiillmmggrrdd wwiitthh ssyysslloogg??
+
+  Output from vmailmgrd can be recorded by either splogger (part of
+  qmail) or with the logger that comes with several flavours of UNIX. To
+  use splogger, pipe the output of vmailmgrd into the command `splogger
+  vmailmgrd'. This will timestamp each entry and tag them with the word
+  `vmailmgrd'. By default, splogger logs to facility 2 (mail). To use
+  logger, pipe the output of vmailmgrd into the comamand `logger -t
+  vmailmgrd -p mail.notice'. See the respective man pages of these two
+  programs for more information.
+
+  Note: The use of syslog for logging messages is strongly discouraged
+  due to problems with inefficent and buggy implementation of syslog.
+
+  22..33..  HHooww ddoo II rreeccoorrdd tthhee oouuttppuutt ooff vvmmaaiillmmggrrdd wwiitthh mmuullttiilloogg??
+
+  Make a directory into which the output will go, for example
+  `/var/log/vmailmgrd'. Pipe the output of vmailmgrd into the command
+  `multilog t /var/log/vmailmgrd'. See the documentation for multilog
+  for more information on how to adjust its output.
+
+  22..44..  HHooww ddoo II sseettuupp VVMMmmaaiillMMggrr IIMMAAPP ssuuppppoorrtt??
+
+  VMailMgr supports Courier-IMAP, but Courier-IMAP does not auto detect
+  VMailMgr.  This means that some minor work is required for making the
+  two work together.
+
+  +o  You must copy `/usr/local/bin/authvmailmgr` to `/usr/lib/courier-
+     imap/libexec/authlib/authvmailmgr`.
+
+  +o  Then modify the `AUTHMODULES` statement in `/usr/lib/courier-
+     imap/etc/imapd.config` and add `authvmailmgr` as the first
+     authentication module.
+
+  22..55..  UUppggrraaddiinngg ffrroomm PPrreevviioouuss VVeerrssiioonnss
+
+  If you are upgrading from an older version, you may need to make some
+  changes to your system before or after doing the upgrade. The
+  following table outlines the necessary changes. Note that you need to
+  follow the instructions for all later versions of the software.
+
+  If you are upgrading from version:
+
+     00..9966..66 oorr eeaarrlliieerr
+        The `vmailmgrd' daemon needs to be run by unixserver, as opposed
+        to being a stand-alone program previously.
+
+     00..9966..22 oorr eeaarrlliieerr
+        Make sure the `vmailmgrd' daemon and vmailmgr CGIs are disabled
+        before upgrading, and upgrade them along with the main package.
+        Changes were made to the daemon interface that will cause adding
+        users and aliases to flake out. As well, the listdomain
+        interface was completely redone.
+
+
+     00..9944 oorr eeaarrlliieerr,, uussiinngg tthhee PPOOPP bbuulllleettiinn ffaacciilliittyy
+        The POP bulletin facility has been moved into a stand-alone
+        program that needs to be executed through `checkvpw-postsetuid'.
+
+
+     00..9933 oorr eeaarrlliieerr
+        If you do not use the CGIs, you no longer need to run the
+        `vmailmgrd' daemon.
+
+
+     00..9922..22 oorr eeaarrlliieerr
+        The configuration changed from reading a single file to reading
+        a set of files in a directory. Read the configuration
+        documentation and run the program `vconf2dir'.
+
+
+     00..9900..22 oorr eeaarrlliieerr
+        The name of the user to which mail to an unknown user is
+        delivered changed from `*' to `+'. If you were using this
+        feature, either change all your domains to accomodate this
+        change, or set the `default-username' config file to contain
+        `*'.
+
+
+     00..8888 oorr eeaarrlliieerr
+        The file format of the virtual password tables has changed from
+        plain text files to CDB tables. You will need to suspend local
+        deliveries before upgrading, and run the program `vpasswd2cdb'
+        as each base user after upgrading, before re-enabling local
+        deliveries.
+
+  22..66..  HHooww ddoo II ccoonnffiigguurree qqmmaaiill++ppaattcchheess ttoo uussee vvmmaaiillmmggrr ffoorr PPOOPP??
+
+  Put the string `checkvpw' into the file
+  `/etc/qmail/control/checkpassword' and restart pop3d by typing
+  `/etc/rc.d/init.d/pop3d restart'.
+
+  22..77..  HHooww ddoo II aallllooww cclliieennttss ttoo rreellaayy SSMMTTPP tthhrroouugghh mmee??
+
+  Download and install relay-ctrl from  <http://em.ca/~bruceg/relay-
+  ctrl/>.  It works with vmailmgr, for both POP3 and IMAP clients.
+
+  33..  UUssaaggee
+
+  33..11..  II ccaann oonnllyy uussee oonnee IIPP aaddddrreessss.. HHooww ddoo II lloogg iinn aass aa vviirrttuuaall
+  uusseerr??
+
+  There are two ways to log in without using multiple IP addresses.
+
+  The first way is to log in as `userSEPvirtual.domain.org', where
+  `user' is the mailbox name of the virtual user, SEP is one of `@' or
+  `:' (by default, this is configurable in the `/etc/vmailmgr/'
+  directory), and `virtual.domain.org' is the virtual domain's name, as
+  listed in `/var/qmail/control/virtualdomains'.
+
+  The second way is to use the internal form of the mailbox name -- that
+  is, `baseuser-user', where `user' is the same as above, and `baseuser'
+  is the username of the managing user.
+
+  Example: `/var/qmail/control/virtualdomains' contains
+
+    testdomain.org:testuser
+
+
+  User `testuser' exists, and has set up a virtual mailbox with the name
+  `v'. The `separators' variable in `/etc/vmailmgr/' contains `@:'. This
+  virtual user could log in as `v@testdomain.org', `v:testdomain.org',
+  or `testuser-v'.
+
+
+
+  33..22..  HHooww ddoo II ggeett aallll mmiissddiirreecctteedd mmaaiill sseenntt ttoo mmee??
+
+  In the `vmailmgr/' configuration directory, there is an entry called
+  `default-username'. If mail to a virtual domain does not match any
+  users or aliases in that domain, it is delivered to the name listed in
+  this configuration item if it exists (which defaults to `+'). To make
+  this deliver to you, simply type:
+
+    vaddalias + me
+
+
+
+  44..  TTrroouubblleesshhoooottiinngg
+
+  44..11..  BBiinndd eerrrroorr mmeessssaaggee ffrroomm vvmmaaiillmmggrrdd..
+
+  If vmailmgrd reports `vmailmgrd: bind: no such file or directory' when
+  you start it up, it means that can't create its socket file.  By
+  default, it will try to create the socket file `/tmp/.vmailmgrd'. You
+  must ensure that `/tmp' is writable, or that the socket is created in
+  some other place by setting `socket-file' in the configuration.
+
+  44..22..  EErrrroorr sseennddiinngg ttoo aann aalliiaass:: qqmmaaiill--qquueeuuee eexxiitteedd wwiitthh aann eerrrroorr!!
+
+  If qmail reports "deferral: vdeliver: qmail-queue exited with an
+  error!", check where your qmail is installed.  On Debian systems, you
+  will need to type "ls -s /usr/sbin /var/qmail/bin", since they've
+  installed the qmail binaries into /usr/sbin.
+
+  44..33..  RRuunnnniinngg vvmmaaiillmmggrrdd ffaaiillss..
+
+  When run by itself, vmailmgrd will report "Timed out waiting for
+  remote".  vmailmgrd needs to be run from unixserver, part of the
+  ucspi-unix package available at  <http://em.ca/~bruceg/ucspi-unix/>.
+
+  44..44..  PPOOPP33 oorr IIMMAAPP llooggiinnss ttaakkee 3300 sseeccoonnddss oorr lloonnggeerr..
+
+  This is almost certainly a DNS lookup problem.  Make sure that DNS
+  lookups aren't timing out, that lookups on all your IP addresses
+  aren't failing, and that you can lookup remote addresses as well.
+
+  If you are using 'tcpserver' for the head end to qmail-pop3d, then you
+  may want to the following 2 switches to the command line: -R and -H.
+  The former prevents tcpserver from attempting to obtain TCPREMOTEINFO
+  from the remote host.  This eliminates an "ident" lookup that may be
+  being blocked or silently dropped by a firewall.  The latter prevents
+  tcpserver from doing a DNS lookup on the remote IP.
+  55..  MMiisscceellllaanneeoouuss
+
+  55..11..  HHooww ddoo II ggeett iinn ccoonnttaacctt wwiitthh ootthheerr uusseerrss??
+
+  There is a mailing list run by the author. To subscribe, send an e-
+  mail (content and subject line is ignored) to  <mailto:vmailmgr-
+  subscribe@lists.em.ca>.
+
+  Remember that if you have a problem that you want us to diagnose, we
+  need to know the following important details:
+
+  1. The output of `qmail-showctl`
+
+  2. The contents of the vmailmgrd log for the attempt you are trying to
+     diagnose
+
+  3. The contents of the qmail and smtpd logs for a failed delivery
+     attempt
+
+  4. The contents of the pop3d logs for a failed login attempt
+
+  5. The complete command line with which vmailmgrd and qmail-pop3d was
+     invoked
+
+     Please do not contact the author directly with vmailmgr questions.
+
+  55..22..  AArree ddeevveellooppmmeenntt vveerrssiioonn ooff vvmmaaiillmmggrr aavvaaiillaabbllee aannyywwhheerree??
+
+  Yes, they are available through anonymous CVS.  To access the CVS
+  server, set your CVSROOT to :pserver:cvs@bruce-
+  guenter.dyndns.org:/CVS, log in with an empty password, and check out
+  the vmailmgr module.
+
+  55..33..  HHooww ddooeess iinnccoommiinngg eemmaaiill ggeett hhaannddlleedd??
+
+  Incoming email is first received by the qmail SMTP daemon and inserted
+  into the qmail queue. Then `qmail-send' examines the email envelope
+  (which details the recipient address or addresses) to determine how to
+  dispatch the message. It looks up the domain name of each recipient in
+  `/var/qmail/control/virtualdomains', and prefixes the user name with
+  the string that it finds. It then looks up the resulting user name in
+  the system password table (or in `/var/qmail/users/cdb' if it exists)
+  to find the base user name and home directory (which I will call
+  `$HOME'). It then looks for the file `$HOME/.qmail-VIRTUAL'. If that's
+  not found, it looks for the file `$HOME/.qmail-default', which will
+  contain an instruction to pipe the message to `vdeliver'.
+
+  This is where vmailmgr first enters the picture. The virtual user name
+  is sent to `vdeliver' through environment variables. It looks in the
+  configuration files (in `$HOME/.vmailmgr' and then in `/etc/vmailmgr')
+  to determine the location of the password table, and looks up the
+  virtual user name in the table to determine delivery instructions. If
+  the name is not found, the message is bounced and delivery ends.
+  Otherwise, it then looks for the `vdeliver-predeliver' script in the
+  configuration directories (in reverse order) and executes any that are
+  found. It then delivers the message to all the listed destinations --
+  an optional mailbox directory and zero or more forwarding addresses.
+  Finally, it looks for the `vdeliver-postdeliver' script and executes
+  any that are found.
+
+  55..44..  HHooww ddooeess oouuttggooiinngg eemmaaiill ggeett hhaannddlleedd??
+
+  Outgoing email is not handled by vmailmgr. For details on outgoing
+  email handling, check the qmail documentation.
+
+
+  55..55..  WWhhaatt aabboouutt sseeccuurriittyy ooff CCGGII aanndd PPHHPP ffuunnccttiioonnss??
+
+  The socket used by the daemon is a UNIX-domain socket (as opposed to
+  Internet-domain), meaning you need local access on the computer to
+  open up a connection.  The path for this socket is run-time
+  configurable.
+
+  The daemon forks a new connection for each connection, up to a
+  configurable maximum (at which point it stops listening, IIRC, I
+  should verify this).  The idea of threading has been completely
+  discarded to avoid a bug in a command creeping in and makeing the
+  whole server break.
+
+  The protocol spoken over the socket is explicitly bounded to at most
+  64kB of data, and all data is prefixed by a size.  Static-sized
+  buffers are only used with static-sized reads, and therefore can't be
+  overflowed with stack-smashing tricks.
+
+  The daemon commands setuid to the appropriate user as soon as the base
+  user has been verified, to avoid doing any more than necessary as
+  root, as well as to avoid the possibility of tricking the daemon into
+  reading a file another user wouldn't normally have access to.
+
+  To help avoid DoS on the local computer, a 1-second alarm is set as
+  soon as the connection is received, and is only cleared once all the
+  data has been read.  If it takes longer than 1 second to read the data
+  from the socket, the server process exits.
+
+  55..66..  WWhhaatt aarree tthhee ddiiffffeerreenncceess bbeettwweeeenn vvmmaaiillmmggrr aanndd vvppooppmmaaiill??
+
+  The primary difference between vmailmgr and vpopmail is the use of
+  base users.  With vmailmgr there is one base user for each virtual
+  domain.  With vpopmail, there is one base user for the entire virtual
+  domain system.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/HOWTO.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,334 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+ <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
+ <TITLE>  VMailMgr HOWTO</TITLE>
+
+
+</HEAD>
+<BODY>
+<H1>  VMailMgr HOWTO</H1>
+
+<H2>Bruce Guenter 
+<A HREF="mailto:bruceg@em.ca">mailto:bruceg@em.ca</A>,
+  Dan Kuykendall 
+<A HREF="mailto:dan@kuykendall.org">mailto:dan@kuykendall.org</A></H2>  v1.w, 2000-09-15
+<P><HR>
+<EM>  This document explains how to setup VMailMgr support pop3 virtual domain   services in conjunction with Qmail.</EM>
+<HR>
+<H2><A NAME="s1">1. Introduction</A></H2>
+
+<P>VMailMgr (short for Virtual MAIL ManaGeR) is a package of programs
+designed to manage multiple domains of mail addresses and mailboxes
+on a single host. It co-operates with qmail for mail delivery and
+program control.
+<H2>1.1 What is VMailMgr and why should I use it?</H2>
+
+<P>VMailMgr is:
+<P> A series of utilities for managing virtual domains
+which include a password checking interface for qmail which replaces
+the usual checkpassword, and an authentication module for Courier
+IMAP, that provide access to the virtual mailboxes by one of three
+methods:
+<UL>
+<LI> IP-based virtual server access (invisible to the POP3 user)</LI>
+<LI> username-based access (username-virtualuser)</LI>
+<LI> hostname-based access (virtualuser@virtual.host or
+virtualuser:virtual.host)</LI>
+</UL>
+<P>You should use it if you prefer to have each domain controlled by a
+seperate username, allowing the use of system quotas and better
+security
+<H2>1.2 New versions </H2>
+
+<P>The newest version of this can be found on the VMailMgr homepage
+<A HREF="http://www.vmailmgr.org/">http://www.vmailmgr.org/</A> in its HTML version as well as
+in the source package SGML source, HTML, and text.  Other versions
+may be found in different formats at the LDP homepage 
+<A HREF="http://www.linuxdoc.org/">http://www.linuxdoc.org/</A>.
+<H2>1.3 Comments </H2>
+
+<P>Comments on this HOWTO should be directed to the VMailMgr mailing
+list.  To subscribe, send an email to 
+<A HREF="mailto:vmailmgr-subscribe@lists.em.ca">vmailmgr-subscribe@lists.em.ca</A>.
+<H2>1.4 History </H2>
+
+<P>This document was started by Bruce Guenter and reworked by Dan
+Kuykendall.
+<H2>1.5 Copyrights and Trademarks </H2>
+
+<P>Copyright (c)  Dan Kuykendall.
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1
+or any later version published by the Free Software Foundation
+<P>A copy of the license is available at 
+<A HREF="http://www.gnu.org/copyleft/fdl.txt">GNU Free   Documentation License</A>.
+<H2>1.6 Acknowledgements and Thanks </H2>
+
+<P>Thanks to Bruce Guenter for VMailMgr and the core of this
+HOWTO. Thanks to Mike Bell, who always seems to have the answers to
+my questions. Finally, thanks to all those on the 
+<A HREF="mailto:vmailmgr@lists.em.ca">vmailmgr@lists.em.ca</A>
+mailing list who have helped me, or asked the same stuff so many
+times that I had to write this to stop the repeat questions.
+<H2><A NAME="s2">2. Installation</A></H2>
+
+<H2>2.1 Get the files</H2>
+
+<P>Visit the VMailMgr website 
+<A HREF="http://www.vmailmgr.org/">http://www.vmailmgr.org/</A> to
+get the package.
+<P>If you get the binary RPMS you will need at least the vmailmgr package.
+<H2>2.2 Install with RPMS</H2>
+
+<H3>Compiling SRC.RPM's</H3>
+
+<P>Simply compile the src.rpm file with the `<CODE>rpm --rebuild</CODE>` command.
+-Example-
+<HR>
+<PRE>
+  rpm -ivh vmailmgr-0.96.9-1.src.rpm
+</PRE>
+<HR>
+<H3>Installing RPM's</H3>
+
+<P>After compiling the source rpms, the binaries will be located 
+in `<CODE>/usr/src/redhat/RPMS/i386/</CODE>` or something similar.
+<P>Simply run the following command for each package
+<PRE>
+  rpm -ivh &lt;location>/&lt;package.i386.rpm>
+</PRE>
+
+-Example-
+<HR>
+<PRE>
+  rpm -ivh /usr/src/redhat/RPMS/i386/vmailmgr-0.96.9-1.i386.rpm
+  rpm -ivh /usr/src/redhat/RPMS/i386/vmailmgr-daemon-0.96.9-1.i386.rpm
+</PRE>
+<HR>
+<P>
+<P>
+<H2>2.3 Install with source</H2>
+
+<P>If you dont ue RPMS you can install from source.
+<P>Run the following command
+<PRE>
+  (As non-root user)
+  tar zxf &lt;package.tar.gz>
+  cd &lt;newly created dir>
+  ./configure
+  make
+  (As root)
+  make install
+</PRE>
+
+-Example-
+<HR>
+<PRE>
+  (As non-root user)
+  tar zxf vmailmgr-0.96.9.tar.gz
+  cd vmailmgr-0.96.9
+  ./configure
+  make
+  (As root)
+  make install
+</PRE>
+<HR>
+
+That should do it.
+<H2><A NAME="s3">3. Setup</A></H2>
+
+<P>In the following setup examples, it is assumed that your binaries
+are installed in `<CODE>/usr/bin</CODE>`, and configuration is in
+`<CODE>/etc/vmailmgr</CODE>`, as is the case if you installed from the
+RPMs.
+If you installed from source, configure puts the binaries into
+`<CODE>/usr/local/bin</CODE>` and the configuration into
+`<CODE>/usr/local/etc/vmailmgr</CODE>` by default.
+<H2>3.1 Setting Up a Virtual Domain</H2>
+
+<P>The following steps are necessary to set up a virtual domain with
+vmailmgr (assuming vmailmgr has been compiled and installed). As an
+example, we'll set up a virtual user `<CODE>me@mydomain.org</CODE>`,
+with aliases of `<CODE>myself@mydomain.org</CODE>` and
+`<CODE>myname@mydomain.org</CODE>`.
+<OL>
+<LI>Set up a DNS entry for the domain. This is not covered here, as it
+is dependant on far too many other things.  I will mention that to
+make IP based virtual domains work a PTR record which matches an
+entry in virtualdomains is nessesary, for example, if nslookup
+10.56.33.122 returns <CODE>mail.mydomain.com</CODE>,
+`<CODE>virtualdomains</CODE>` needs an entry like
+`<CODE>mail.mydomain.com:myuser</CODE>'
+For the example, we'll assume that the mail exchanger for
+mydomain.org is already set up to point to your computer.</LI>
+<LI>Set up a base user for the domain. Create a user, with a name of
+your choosing.  Since the maildirs for all the users in the
+virtual domain will be stored under this user's home directory,
+make sure you set the user up in a partition or disk that is
+appropriate for such storage. The tools that you should use to
+accomplish this step vary greatly between different systems. For
+our example, I'll add a user `<CODE>myuser</CODE>`.</LI>
+<LI>Configure qmail to recognize the domain. To do this, you need to
+modify two of qmail's configuration files in
+`<CODE>/var/qmail/control</CODE>` `<CODE>rcpthosts</CODE>` and
+`<CODE>virtualdomains</CODE>`.
+<UL>
+<LI>To `<CODE>rcpthosts</CODE>` :
+add the line `<CODE>mydomain.org</CODE>`. </LI>
+<LI>To `<CODE>virtualdomains</CODE>` :
+add the line `<CODE>mydomain.org:myuser</CODE>`.</LI>
+</UL>
+
+If you wish to have mail to `<CODE>anything.mydomain.org</CODE>`
+be delivered in the same way, add the following
+<UL>
+<LI>To `<CODE>rcpthosts</CODE>` :
+add the line `<CODE>.mydomain.org</CODE>`. </LI>
+<LI>To `<CODE>virtualdomains</CODE>` :
+add the line `<CODE>.mydomain.org:myuser</CODE>`.</LI>
+</UL>
+</LI>
+<LI>Configure qmail-popup/qmail-pop3d to use `<CODE>checkvpw</CODE>` as
+the password checker. This step is dependant on how you have
+installed qmail.
+<UL>
+<LI>Replace `<CODE>checkpassword</CODE>` in the command you use to
+invoke qmail-popup/qmail-pop3d (either in
+`<CODE>/etc/inet.conf</CODE>` or in a `<CODE>tcpserver</CODE>`
+command) with `<CODE>checkvpw</CODE>`.</LI>
+<LI>And/Or at the prompt type: `<CODE>echo checkvpw >
+/var/qmail/control/checkpassword</CODE>`</LI>
+</UL>
+</LI>
+<LI>Set up the vmailmgr files:
+<UL>
+<LI>Either change user to the user you just created (for example,
+type `<CODE>su - myuser</CODE>`) or log in (with either telnet or
+at the console) as the new user.</LI>
+<LI>Set up the base vmailmgr files by running `<CODE>vsetup</CODE>`.</LI>
+<LI>Use the included programs to add users and aliases.
+For our example, we would type the following commands:
+<PRE>
+  vadduser me
+  vaddalias myself me
+  vaddalias myname me
+</PRE>
+</LI>
+</UL>
+</LI>
+</OL>
+
+After you have completed all these steps, you will need to kill and
+restart `<CODE>qmail-send</CODE>` to make it read the new
+`<CODE>virtualdomains</CODE>` table.
+<P>If you are using `<CODE>inetd</CODE>` to launch `<CODE>qmail-popup</CODE>`,
+`<CODE>kill -HUP</CODE>` the `<CODE>inetd</CODE>` process as well.
+<H2>3.2 Using one IP address for mutiple domains</H2>
+
+<P>There are two ways to log in without using multiple IP addresses. 
+<P>
+<OL>
+<LI>The first way is to log in as
+`<CODE>userSEPvirtual.domain.org</CODE>`, where `<CODE>user</CODE>` is the
+mailbox name of the virtual user, SEP is one of `<CODE>@</CODE>` or
+`<CODE>:</CODE>` (by default, this is configurable in the
+`<CODE>/etc/vmailmgr/</CODE>' directory), and
+`<CODE>virtual.domain.org</CODE>' is the virtual domain's name, as
+listed in `<CODE>/var/qmail/control/virtualdomains</CODE>'.</LI>
+<LI>The second way is to use the internal form of the mailbox name --
+that is, `<CODE>baseuser-user</CODE>', where `<CODE>user</CODE>' is the
+same as above, and `<CODE>baseuser</CODE>' is the username of the
+managing user.</LI>
+</OL>
+
+Example: `<CODE>/var/qmail/control/virtualdomains</CODE>' contains 
+<PRE>
+  testdomain.org:testuser
+</PRE>
+
+User `<CODE>myuser</CODE>' exists, and has set up a virtual mailbox with
+the name `<CODE>me</CODE>'. The `<CODE>separators</CODE>' variable in
+`<CODE>/etc/vmailmgr/</CODE>' contains `<CODE>@:</CODE>'. This virtual user
+could log in as `<CODE>me@mydomain.com</CODE>',
+`<CODE>me:mydomain.cm</CODE>', or `<CODE>myuser-me</CODE>'.
+<P>
+<P>
+<H2>3.3 Catching all misdirected mail in a virtual domain</H2>
+
+<P>In the `<CODE>vmailmgr/</CODE>' configuration directory, there is an
+entry called `<CODE>default-username</CODE>'. If mail to a virtual
+domain does not match any users or aliases in that domain, it is
+delivered to the name listed in this configuration item if it exists
+(which defaults to `<CODE>+</CODE>'). To make this deliver to you,
+simply type:
+<PRE>
+  vaddalias + me
+</PRE>
+<H2>3.4 VMailMgr IMAP support</H2>
+
+<P>VMailMgr supports Courier-IMAP, but Courier-IMAP does not come with
+an authentication module for VMailMgr.  This means that some minor
+work is required for making the two work together.
+<UL>
+<LI>You must copy `<CODE>/usr/bin/authvmailmgr</CODE>` to
+`<CODE>/usr/lib/courier-imap/libexec/authlib/authvmailmgr</CODE>`.</LI>
+<LI>Then modify the `<CODE>AUTHMODULES</CODE>` statement in
+`<CODE>/usr/lib/courier-imap/etc/imapd.config</CODE>` and add
+`<CODE>authvmailmgr</CODE>` as the first authentication module.</LI>
+</UL>
+<H2>3.5 Enabling enforcement of virtual user quotas</H2>
+
+<P>VMailMgr supports per-virtual-user quotas, but not out of the box,
+as it is not needed by the majority of users, and requires an extra
+program to be run on each delivery.
+To configure quota support, create the file
+`<CODE>/etc/vmailmgr/vdeliver-predeliver</CODE>`, containing
+the following:
+<PRE>
+  #!/bin/sh
+  /usr/bin/vcheckquota
+</PRE>
+
+This is executed as a shell script, so you will need to make it
+executable by running the following command:
+<PRE>
+  chmod +x /etc/vmailmgr/vdeliver-predeliver
+</PRE>
+<H2>3.6 Enabling processing of autoresponses</H2>
+
+<P>Download and install the qmail-autoresponder package, found at
+<A HREF="http://em.ca/~bruceg/qmail-autoresponder/">http://em.ca/~bruceg/qmail-autoresponder/</A>.
+As with the above section, create a shell script
+`<CODE>/etc/vmailmgr/vdeliver-postdeliver</CODE>`, containing the
+following:
+<PRE>
+  #!/bin/sh
+  if test -s $MAILDIR/autoresponse/message.txt
+  then
+    qmail-autoresponder $MAILDIR/autoresponse/message.txt $MAILDIR/autoresponse
+  fi
+</PRE>
+<H2>3.7 Web-based interfaces for vmailmgr</H2>
+
+<P>There are currently a few working solutions to administrate
+your vmailmgr system via a web interface. Only requirement is
+that the vmailmgrd daemon is running, and that you have
+a webserver on your system.
+<OL>
+<LI>For Python fans, there is vpyadmin by Bruce Guenter. The files can
+be downloaded at 
+<A HREF="http://em.ca/~bruceg/vpyadmin/">http://em.ca/~bruceg/vpyadmin/</A>, and
+the development code is online at 
+<A HREF="http://bruce-guenter.dyndns.org/cgi-bin/vpyadmin/">http://bruce-guenter.dyndns.org/cgi-bin/vpyadmin/</A>
+(sample.org / samplevm).</LI>
+<LI>And if you like PHP, you can use oMail-admin by Olivier Müller:
+it fully supports all vmailmgr functions, and speaks englich,
+french, italian, spanish, german and russian. Project homepage:
+<A HREF="http://omail.omnis.ch">http://omail.omnis.ch</A>. Online demo:
+<A HREF="http://admin.omnis.ch/omail/">http://admin.omnis.ch/omail/</A> (test.com / test).</LI>
+<LI>And there are also C-based CGI scripts in the <CODE>cgi</CODE>
+directory of the vmailmgr distribution.</LI>
+</OL>
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/HOWTO.sgml	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,372 @@
+<!doctype linuxdoc system>
+
+<!-- LinuxDoc file was created by hand by <Dan Kuykendall> Wed April 23 -->
+<article>
+<title>
+  VMailMgr HOWTO
+</title>
+<author>
+  Bruce Guenter <url url="mailto:bruceg@em.ca">,
+  Dan Kuykendall <url url="mailto:dan@kuykendall.org">
+</author>
+<date>
+  v1.w, 2000-09-15
+</date>
+<abstract>
+  This document explains how to setup VMailMgr support pop3 virtual domain 
+  services in conjunction with Qmail.
+</abstract>
+
+<toc>
+
+<sect>Introduction
+<p>
+  VMailMgr (short for Virtual MAIL ManaGeR) is a package of programs
+  designed to manage multiple domains of mail addresses and mailboxes
+  on a single host. It co-operates with qmail for mail delivery and
+  program control.
+</p>
+
+<sect1>What is VMailMgr and why should I use it?
+<p>
+  VMailMgr is:<p> A series of utilities for managing virtual domains
+  which include a password checking interface for qmail which replaces
+  the usual checkpassword, and an authentication module for Courier
+  IMAP, that provide access to the virtual mailboxes by one of three
+  methods:
+<itemize>
+  <item> IP-based virtual server access (invisible to the POP3 user)
+  <item> username-based access (username-virtualuser)
+  <item> hostname-based access (virtualuser@virtual.host or
+  virtualuser:virtual.host)
+</itemize>
+
+  You should use it if you prefer to have each domain controlled by a
+  seperate username, allowing the use of system quotas and better
+  security
+</p>
+
+<sect1>New versions 
+<p>
+  The newest version of this can be found on the VMailMgr homepage
+  <url url="http://www.vmailmgr.org/"> in its HTML version as well as
+  in the source package SGML source, HTML, and text.  Other versions
+  may be found in different formats at the LDP homepage <url
+  url="http://www.linuxdoc.org/">.
+</p>
+
+<sect1>Comments 
+<p>
+  Comments on this HOWTO should be directed to the VMailMgr mailing
+  list.  To subscribe, send an email to <url
+  url="mailto:vmailmgr-subscribe@lists.em.ca"
+  name="vmailmgr-subscribe@lists.em.ca">.
+</p>
+
+<sect1>History 
+<p>
+  This document was started by Bruce Guenter and reworked by Dan
+  Kuykendall.
+</p>
+
+<sect1>Copyrights and Trademarks 
+<p>
+  Copyright (c)  Dan Kuykendall.
+  Permission is granted to copy, distribute and/or modify this document
+  under the terms of the GNU Free Documentation License, Version 1.1
+  or any later version published by the Free Software Foundation
+</p>
+<p>
+  A copy of the license is available at <url
+  url="http://www.gnu.org/copyleft/fdl.txt" name="GNU Free
+  Documentation License">.
+</p>
+
+<sect1>Acknowledgements and Thanks 
+<p>
+  Thanks to Bruce Guenter for VMailMgr and the core of this
+  HOWTO. Thanks to Mike Bell, who always seems to have the answers to
+  my questions. Finally, thanks to all those on the <url
+  url="mailto:vmailmgr@lists.em.ca" name="vmailmgr@lists.em.ca">
+  mailing list who have helped me, or asked the same stuff so many
+  times that I had to write this to stop the repeat questions.
+</p>
+
+<sect>Installation
+
+<sect1>Get the files
+<p>
+  Visit the VMailMgr website <url url="http://www.vmailmgr.org/"> to
+  get the package.
+<p>
+  If you get the binary RPMS you will need at least the vmailmgr package.
+</p>
+
+<sect1>Install with RPMS
+<sect2>Compiling SRC.RPM's
+<p>
+  Simply compile the src.rpm file with the `<tt>rpm --rebuild</tt>` command.
+  -Example-
+<code>
+  rpm -ivh vmailmgr-0.96.9-1.src.rpm
+</code>
+<sect2>Installing RPM's
+<p>
+  After compiling the source rpms, the binaries will be located 
+  in `<tt>/usr/src/redhat/RPMS/i386/</tt>` or something similar.
+
+  Simply run the following command for each package
+<verb>
+  rpm -ivh <location>/<package.i386.rpm>
+</verb>
+  -Example-
+<code>
+  rpm -ivh /usr/src/redhat/RPMS/i386/vmailmgr-0.96.9-1.i386.rpm
+  rpm -ivh /usr/src/redhat/RPMS/i386/vmailmgr-daemon-0.96.9-1.i386.rpm
+</code>
+
+
+<sect1>Install with source
+<p>
+  If you dont ue RPMS you can install from source.<p>
+  Run the following command
+<verb>
+  (As non-root user)
+  tar zxf <package.tar.gz>
+  cd <newly created dir>
+  ./configure
+  make
+  (As root)
+  make install
+</verb>
+  -Example-
+<code>
+  (As non-root user)
+  tar zxf vmailmgr-0.96.9.tar.gz
+  cd vmailmgr-0.96.9
+  ./configure
+  make
+  (As root)
+  make install
+</code>
+  That should do it.
+</p>
+
+<sect>Setup
+
+<p>
+  In the following setup examples, it is assumed that your binaries
+  are installed in `<tt>/usr/bin</tt>`, and configuration is in
+  `<tt>/etc/vmailmgr</tt>`, as is the case if you installed from the
+  RPMs.
+  If you installed from source, configure puts the binaries into
+  `<tt>/usr/local/bin</tt>` and the configuration into
+  `<tt>/usr/local/etc/vmailmgr</tt>` by default.
+</p>
+
+<sect1>Setting Up a Virtual Domain
+<p>
+  The following steps are necessary to set up a virtual domain with
+  vmailmgr (assuming vmailmgr has been compiled and installed). As an
+  example, we'll set up a virtual user `<tt>me@mydomain.org</tt>`,
+  with aliases of `<tt>myself@mydomain.org</tt>` and
+  `<tt>myname@mydomain.org</tt>`.
+<enum>
+  <item>
+    Set up a DNS entry for the domain. This is not covered here, as it
+    is dependant on far too many other things.  I will mention that to
+    make IP based virtual domains work a PTR record which matches an
+    entry in virtualdomains is nessesary, for example, if nslookup
+    10.56.33.122 returns <tt>mail.mydomain.com</tt>,
+    `<tt>virtualdomains</tt>` needs an entry like
+    `<tt>mail.mydomain.com:myuser</tt>'
+    For the example, we'll assume that the mail exchanger for
+    mydomain.org is already set up to point to your computer.
+  <item>
+    Set up a base user for the domain. Create a user, with a name of
+    your choosing.  Since the maildirs for all the users in the
+    virtual domain will be stored under this user's home directory,
+    make sure you set the user up in a partition or disk that is
+    appropriate for such storage. The tools that you should use to
+    accomplish this step vary greatly between different systems. For
+    our example, I'll add a user `<tt>myuser</tt>`.
+  <item>
+    Configure qmail to recognize the domain. To do this, you need to
+    modify two of qmail's configuration files in
+    `<tt>/var/qmail/control</tt>` `<tt>rcpthosts</tt>` and
+    `<tt>virtualdomains</tt>`.
+    <itemize>
+      <item>To `<tt>rcpthosts</tt>` :
+        add the line `<tt>mydomain.org</tt>`. 
+      <item>To `<tt>virtualdomains</tt>` :
+        add the line `<tt>mydomain.org:myuser</tt>`.
+    </itemize>
+        If you wish to have mail to `<tt>anything.mydomain.org</tt>`
+        be delivered in the same way, add the following
+    <itemize>
+      <item>To `<tt>rcpthosts</tt>` :
+        add the line `<tt>.mydomain.org</tt>`. 
+      <item>To `<tt>virtualdomains</tt>` :
+        add the line `<tt>.mydomain.org:myuser</tt>`.
+    </itemize>
+  <item>
+    Configure qmail-popup/qmail-pop3d to use `<tt>checkvpw</tt>` as
+    the password checker. This step is dependant on how you have
+    installed qmail.
+    <itemize>
+      <item>
+        Replace `<tt>checkpassword</tt>` in the command you use to
+        invoke qmail-popup/qmail-pop3d (either in
+        `<tt>/etc/inet.conf</tt>` or in a `<tt>tcpserver</tt>`
+        command) with `<tt>checkvpw</tt>`.
+      <item>
+        And/Or at the prompt type: `<tt>echo checkvpw >
+        /var/qmail/control/checkpassword</tt>`
+    </itemize>
+  <item>
+    Set up the vmailmgr files:
+    <itemize>
+      <item>
+        Either change user to the user you just created (for example,
+        type `<tt>su - myuser</tt>`) or log in (with either telnet or
+        at the console) as the new user.
+      <item>
+        Set up the base vmailmgr files by running `<tt>vsetup</tt>`.
+      <item>
+        Use the included programs to add users and aliases.
+        For our example, we would type the following commands:
+<verb>
+  vadduser me
+  vaddalias myself me
+  vaddalias myname me
+</verb>
+     </itemize>
+</enum>
+  After you have completed all these steps, you will need to kill and
+  restart `<tt>qmail-send</tt>` to make it read the new
+  `<tt>virtualdomains</tt>` table.
+<p>
+  If you are using `<tt>inetd</tt>` to launch `<tt>qmail-popup</tt>`,
+  `<tt>kill -HUP</tt>` the `<tt>inetd</tt>` process as well.
+</p>
+
+<sect1>Using one IP address for mutiple domains
+<p>
+  There are two ways to log in without using multiple IP addresses. 
+<p>
+<enum>
+  <item>
+    The first way is to log in as
+    `<tt>userSEPvirtual.domain.org</tt>`, where `<tt>user</tt>` is the
+    mailbox name of the virtual user, SEP is one of `<tt>@</tt>` or
+    `<tt>:</tt>` (by default, this is configurable in the
+    `<tt>/etc/vmailmgr/</tt>' directory), and
+    `<tt>virtual.domain.org</tt>' is the virtual domain's name, as
+    listed in `<tt>/var/qmail/control/virtualdomains</tt>'.
+  <item>
+    The second way is to use the internal form of the mailbox name --
+    that is, `<tt>baseuser-user</tt>', where `<tt>user</tt>' is the
+    same as above, and `<tt>baseuser</tt>' is the username of the
+    managing user.
+</enum>
+  Example: `<tt>/var/qmail/control/virtualdomains</tt>' contains 
+<verb>
+  testdomain.org:testuser
+</verb>
+  User `<tt>myuser</tt>' exists, and has set up a virtual mailbox with
+  the name `<tt>me</tt>'. The `<tt>separators</tt>' variable in
+  `<tt>/etc/vmailmgr/</tt>' contains `<tt>@:</tt>'. This virtual user
+  could log in as `<tt>me@mydomain.com</tt>',
+  `<tt>me:mydomain.cm</tt>', or `<tt>myuser-me</tt>'.
+<p>
+
+<sect1>Catching all misdirected mail in a virtual domain
+<p>
+  In the `<tt>vmailmgr/</tt>' configuration directory, there is an
+  entry called `<tt>default-username</tt>'. If mail to a virtual
+  domain does not match any users or aliases in that domain, it is
+  delivered to the name listed in this configuration item if it exists
+  (which defaults to `<tt>+</tt>'). To make this deliver to you,
+  simply type:
+<verb>
+  vaddalias + me
+</verb>
+</p>
+
+<sect1>VMailMgr IMAP support
+<p>
+  VMailMgr supports Courier-IMAP, but Courier-IMAP does not come with
+  an authentication module for VMailMgr.  This means that some minor
+  work is required for making the two work together.
+<itemize>
+  <item>
+    You must copy `<tt>/usr/bin/authvmailmgr</tt>` to
+    `<tt>/usr/lib/courier-imap/libexec/authlib/authvmailmgr</tt>`.
+  <item>
+    Then modify the `<tt>AUTHMODULES</tt>` statement in
+    `<tt>/usr/lib/courier-imap/etc/imapd.config</tt>` and add
+    `<tt>authvmailmgr</tt>` as the first authentication module.
+</itemize>
+</p>
+
+<sect1>Enabling enforcement of virtual user quotas
+<p>
+  VMailMgr supports per-virtual-user quotas, but not out of the box,
+  as it is not needed by the majority of users, and requires an extra
+  program to be run on each delivery.
+  To configure quota support, create the file
+  `<tt>/etc/vmailmgr/vdeliver-predeliver</tt>`, containing
+  the following:
+<verb>
+  #!/bin/sh
+  /usr/bin/vcheckquota
+</verb>
+  This is executed as a shell script, so you will need to make it
+  executable by running the following command:
+<verb>
+  chmod +x /etc/vmailmgr/vdeliver-predeliver
+</verb>
+</p>
+
+<sect1>Enabling processing of autoresponses
+<p>
+  Download and install the qmail-autoresponder package, found at
+  <url url="http://em.ca/~bruceg/qmail-autoresponder/">.
+  As with the above section, create a shell script
+  `<tt>/etc/vmailmgr/vdeliver-postdeliver</tt>`, containing the
+  following:
+<verb>
+  #!/bin/sh
+  if test -s $MAILDIR/autoresponse/message.txt
+  then
+    qmail-autoresponder $MAILDIR/autoresponse/message.txt $MAILDIR/autoresponse
+  fi
+</verb>
+</p>
+
+<sect1>Web-based interfaces for vmailmgr
+<p>
+  There are currently a few working solutions to administrate
+  your vmailmgr system via a web interface. Only requirement is
+  that the vmailmgrd daemon is running, and that you have
+  a webserver on your system.
+<enum>
+  <item>
+    For Python fans, there is vpyadmin by Bruce Guenter. The files can
+    be downloaded at <url url="http://em.ca/~bruceg/vpyadmin/">, and
+    the development code is online at <url
+    url="http://bruce-guenter.dyndns.org/cgi-bin/vpyadmin/">
+    (sample.org / samplevm).
+  <item>
+    And if you like PHP, you can use oMail-admin by Olivier Müller:
+    it fully supports all vmailmgr functions, and speaks englich,
+    french, italian, spanish, german and russian. Project homepage:
+    <url url="http://omail.omnis.ch">. Online demo:
+    <url url="http://admin.omnis.ch/omail/"> (test.com / test).
+  <item>
+    And there are also C-based CGI scripts in the <tt>cgi</tt>
+    directory of the vmailmgr distribution.
+</enum>
+</p>
+
+</article>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/HOWTO.txt	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,396 @@
+  VMailMgr HOWTO
+  Bruce Guenter  <mailto:bruceg@em.ca>, Dan Kuykendall
+  <mailto:dan@kuykendall.org>
+  v1.w, 2000-09-15
+
+  This document explains how to setup VMailMgr support pop3 virtual
+  domain   services in conjunction with Qmail.
+  ______________________________________________________________________
+
+  Table of Contents
+
+
+  1. Introduction
+
+     1.1 What is VMailMgr and why should I use it?
+     1.2 New versions
+     1.3 Comments
+     1.4 History
+     1.5 Copyrights and Trademarks
+     1.6 Acknowledgements and Thanks
+
+  2. Installation
+
+     2.1 Get the files
+     2.2 Install with RPMS
+        2.2.1 Compiling SRC.RPM's
+        2.2.2 Installing RPM's
+     2.3 Install with source
+
+  3. Setup
+
+     3.1 Setting Up a Virtual Domain
+     3.2 Using one IP address for mutiple domains
+     3.3 Catching all misdirected mail in a virtual domain
+     3.4 VMailMgr IMAP support
+     3.5 Enabling enforcement of virtual user quotas
+     3.6 Enabling processing of autoresponses
+     3.7 Web-based interfaces for vmailmgr
+
+
+  ______________________________________________________________________
+
+  11..  IInnttrroodduuccttiioonn
+
+  VMailMgr (short for Virtual MAIL ManaGeR) is a package of programs
+  designed to manage multiple domains of mail addresses and mailboxes on
+  a single host. It co-operates with qmail for mail delivery and program
+  control.
+
+  11..11..  WWhhaatt iiss VVMMaaiillMMggrr aanndd wwhhyy sshhoouulldd II uussee iitt??
+
+  VMailMgr is:
+
+  A series of utilities for managing virtual domains which include a
+  password checking interface for qmail which replaces the usual
+  checkpassword, and an authentication module for Courier IMAP, that
+  provide access to the virtual mailboxes by one of three methods:
+
+  +o  IP-based virtual server access (invisible to the POP3 user)
+
+  +o  username-based access (username-virtualuser)
+
+  +o  hostname-based access (virtualuser@virtual.host or
+     virtualuser:virtual.host)
+
+
+  You should use it if you prefer to have each domain controlled by a
+  seperate username, allowing the use of system quotas and better
+  security
+
+  11..22..  NNeeww vveerrssiioonnss
+
+  The newest version of this can be found on the VMailMgr homepage
+  <http://www.vmailmgr.org/> in its HTML version as well as in the
+  source package SGML source, HTML, and text.  Other versions may be
+  found in different formats at the LDP homepage
+  <http://www.linuxdoc.org/>.
+
+  11..33..  CCoommmmeennttss
+
+  Comments on this HOWTO should be directed to the VMailMgr mailing
+  list.  To subscribe, send an email to vmailmgr-subscribe@lists.em.ca
+  <mailto:vmailmgr-subscribe@lists.em.ca>.
+
+  11..44..  HHiissttoorryy
+
+  This document was started by Bruce Guenter and reworked by Dan
+  Kuykendall.
+
+  11..55..  CCooppyyrriigghhttss aanndd TTrraaddeemmaarrkkss
+
+  Copyright (c)  Dan Kuykendall.  Permission is granted to copy,
+  distribute and/or modify this document under the terms of the GNU Free
+  Documentation License, Version 1.1 or any later version published by
+  the Free Software Foundation
+
+  A copy of the license is available at GNU Free   Documentation License
+  <http://www.gnu.org/copyleft/fdl.txt>.
+
+  11..66..  AAcckknnoowwlleeddggeemmeennttss aanndd TThhaannkkss
+
+  Thanks to Bruce Guenter for VMailMgr and the core of this HOWTO.
+  Thanks to Mike Bell, who always seems to have the answers to my
+  questions. Finally, thanks to all those on the vmailmgr@lists.em.ca
+  <mailto:vmailmgr@lists.em.ca> mailing list who have helped me, or
+  asked the same stuff so many times that I had to write this to stop
+  the repeat questions.
+
+  22..  IInnssttaallllaattiioonn
+
+  22..11..  GGeett tthhee ffiilleess
+
+  Visit the VMailMgr website  <http://www.vmailmgr.org/> to get the
+  package.
+
+  If you get the binary RPMS you will need at least the vmailmgr
+  package.
+
+  22..22..  IInnssttaallll wwiitthh RRPPMMSS
+
+  22..22..11..  CCoommppiilliinngg SSRRCC..RRPPMM''ss
+
+  Simply compile the src.rpm file with the `rpm --rebuild` command.
+  -Example-
+
+  ______________________________________________________________________
+    rpm -ivh vmailmgr-0.96.9-1.src.rpm
+  ______________________________________________________________________
+
+
+
+
+  22..22..22..  IInnssttaalllliinngg RRPPMM''ss
+
+  After compiling the source rpms, the binaries will be located in
+  `/usr/src/redhat/RPMS/i386/` or something similar.
+
+  Simply run the following command for each package
+
+    rpm -ivh <location>/<package.i386.rpm>
+
+
+  -Example-
+
+  ______________________________________________________________________
+    rpm -ivh /usr/src/redhat/RPMS/i386/vmailmgr-0.96.9-1.i386.rpm
+    rpm -ivh /usr/src/redhat/RPMS/i386/vmailmgr-daemon-0.96.9-1.i386.rpm
+  ______________________________________________________________________
+
+
+
+
+
+  22..33..  IInnssttaallll wwiitthh ssoouurrccee
+
+  If you dont ue RPMS you can install from source.
+
+  Run the following command
+
+    (As non-root user)
+    tar zxf <package.tar.gz>
+    cd <newly created dir>
+    ./configure
+    make
+    (As root)
+    make install
+
+
+  -Example-
+
+  ______________________________________________________________________
+    (As non-root user)
+    tar zxf vmailmgr-0.96.9.tar.gz
+    cd vmailmgr-0.96.9
+    ./configure
+    make
+    (As root)
+    make install
+  ______________________________________________________________________
+
+
+  That should do it.
+
+  33..  SSeettuupp
+
+  In the following setup examples, it is assumed that your binaries are
+  installed in `/usr/bin`, and configuration is in `/etc/vmailmgr`, as
+  is the case if you installed from the RPMs.  If you installed from
+  source, configure puts the binaries into `/usr/local/bin` and the
+  configuration into `/usr/local/etc/vmailmgr` by default.
+
+  33..11..  SSeettttiinngg UUpp aa VViirrttuuaall DDoommaaiinn
+
+  The following steps are necessary to set up a virtual domain with
+  vmailmgr (assuming vmailmgr has been compiled and installed). As an
+  example, we'll set up a virtual user `me@mydomain.org`, with aliases
+  of `myself@mydomain.org` and `myname@mydomain.org`.
+
+  1. Set up a DNS entry for the domain. This is not covered here, as it
+     is dependant on far too many other things.  I will mention that to
+     make IP based virtual domains work a PTR record which matches an
+     entry in virtualdomains is nessesary, for example, if nslookup
+     10.56.33.122 returns mail.mydomain.com, `virtualdomains` needs an
+     entry like `mail.mydomain.com:myuser' For the example, we'll assume
+     that the mail exchanger for mydomain.org is already set up to point
+     to your computer.
+
+  2. Set up a base user for the domain. Create a user, with a name of
+     your choosing.  Since the maildirs for all the users in the virtual
+     domain will be stored under this user's home directory, make sure
+     you set the user up in a partition or disk that is appropriate for
+     such storage. The tools that you should use to accomplish this step
+     vary greatly between different systems. For our example, I'll add a
+     user `myuser`.
+
+  3. Configure qmail to recognize the domain. To do this, you need to
+     modify two of qmail's configuration files in `/var/qmail/control`
+     `rcpthosts` and `virtualdomains`.
+
+  +o  To `rcpthosts` : add the line `mydomain.org`.
+
+  +o  To `virtualdomains` : add the line `mydomain.org:myuser`.
+
+     If you wish to have mail to `anything.mydomain.org` be delivered in
+     the same way, add the following
+
+  +o  To `rcpthosts` : add the line `.mydomain.org`.
+
+  +o  To `virtualdomains` : add the line `.mydomain.org:myuser`.
+
+  4. Configure qmail-popup/qmail-pop3d to use `checkvpw` as the password
+     checker. This step is dependant on how you have installed qmail.
+
+  +o  Replace `checkpassword` in the command you use to invoke qmail-
+     popup/qmail-pop3d (either in `/etc/inet.conf` or in a `tcpserver`
+     command) with `checkvpw`.
+
+  +o  And/Or at the prompt type: `echo checkvpw >
+     /var/qmail/control/checkpassword`
+
+  5. Set up the vmailmgr files:
+
+  +o  Either change user to the user you just created (for example, type
+     `su - myuser`) or log in (with either telnet or at the console) as
+     the new user.
+
+  +o  Set up the base vmailmgr files by running `vsetup`.
+
+  +o  Use the included programs to add users and aliases.  For our
+     example, we would type the following commands:
+
+       vadduser me
+       vaddalias myself me
+       vaddalias myname me
+
+
+
+  After you have completed all these steps, you will need to kill and
+  restart `qmail-send` to make it read the new `virtualdomains` table.
+
+  If you are using `inetd` to launch `qmail-popup`, `kill -HUP` the
+  `inetd` process as well.
+
+
+  33..22..  UUssiinngg oonnee IIPP aaddddrreessss ffoorr mmuuttiippllee ddoommaaiinnss
+
+  There are two ways to log in without using multiple IP addresses.
+
+
+  1. The first way is to log in as `userSEPvirtual.domain.org`, where
+     `user` is the mailbox name of the virtual user, SEP is one of `@`
+     or `:` (by default, this is configurable in the `/etc/vmailmgr/'
+     directory), and `virtual.domain.org' is the virtual domain's name,
+     as listed in `/var/qmail/control/virtualdomains'.
+
+  2. The second way is to use the internal form of the mailbox name --
+     that is, `baseuser-user', where `user' is the same as above, and
+     `baseuser' is the username of the managing user.
+
+     Example: `/var/qmail/control/virtualdomains' contains
+
+       testdomain.org:testuser
+
+
+  User `myuser' exists, and has set up a virtual mailbox with the name
+  `me'. The `separators' variable in `/etc/vmailmgr/' contains `@:'.
+  This virtual user could log in as `me@mydomain.com', `me:mydomain.cm',
+  or `myuser-me'.
+
+
+
+  33..33..  CCaattcchhiinngg aallll mmiissddiirreecctteedd mmaaiill iinn aa vviirrttuuaall ddoommaaiinn
+
+  In the `vmailmgr/' configuration directory, there is an entry called
+  `default-username'. If mail to a virtual domain does not match any
+  users or aliases in that domain, it is delivered to the name listed in
+  this configuration item if it exists (which defaults to `+'). To make
+  this deliver to you, simply type:
+
+    vaddalias + me
+
+
+
+  33..44..  VVMMaaiillMMggrr IIMMAAPP ssuuppppoorrtt
+
+  VMailMgr supports Courier-IMAP, but Courier-IMAP does not come with an
+  authentication module for VMailMgr.  This means that some minor work
+  is required for making the two work together.
+
+  +o  You must copy `/usr/bin/authvmailmgr` to `/usr/lib/courier-
+     imap/libexec/authlib/authvmailmgr`.
+
+  +o  Then modify the `AUTHMODULES` statement in `/usr/lib/courier-
+     imap/etc/imapd.config` and add `authvmailmgr` as the first
+     authentication module.
+
+  33..55..  EEnnaabblliinngg eennffoorrcceemmeenntt ooff vviirrttuuaall uusseerr qquuoottaass
+
+  VMailMgr supports per-virtual-user quotas, but not out of the box, as
+  it is not needed by the majority of users, and requires an extra
+  program to be run on each delivery.  To configure quota support,
+  create the file `/etc/vmailmgr/vdeliver-predeliver`, containing the
+  following:
+
+    #!/bin/sh
+    /usr/bin/vcheckquota
+
+
+  This is executed as a shell script, so you will need to make it exe-
+  cutable by running the following command:
+    chmod +x /etc/vmailmgr/vdeliver-predeliver
+
+
+
+  33..66..  EEnnaabblliinngg pprroocceessssiinngg ooff aauuttoorreessppoonnsseess
+
+  Download and install the qmail-autoresponder package, found at
+  <http://em.ca/~bruceg/qmail-autoresponder/>.  As with the above
+  section, create a shell script `/etc/vmailmgr/vdeliver-postdeliver`,
+  containing the following:
+
+    #!/bin/sh
+    if test -s $MAILDIR/autoresponse/message.txt
+    then
+      qmail-autoresponder $MAILDIR/autoresponse/message.txt $MAILDIR/autoresponse
+    fi
+
+
+
+  33..77..  WWeebb--bbaasseedd iinntteerrffaacceess ffoorr vvmmaaiillmmggrr
+
+  There are currently a few working solutions to administrate your
+  vmailmgr system via a web interface. Only requirement is that the
+  vmailmgrd daemon is running, and that you have a webserver on your
+  system.
+
+  1. For Python fans, there is vpyadmin by Bruce Guenter. The files can
+     be downloaded at  <http://em.ca/~bruceg/vpyadmin/>, and the
+     development code is online at  <http://bruce-
+     guenter.dyndns.org/cgi-bin/vpyadmin/> (sample.org / samplevm).
+
+  2. And if you like PHP, you can use oMail-admin by Olivier Mller: it
+     fully supports all vmailmgr functions, and speaks englich, french,
+     italian, spanish, german and russian. Project homepage:
+     <http://omail.omnis.ch>. Online demo:
+     <http://admin.omnis.ch/omail/> (test.com / test).
+
+  3. And there are also C-based CGI scripts in the cgi directory of the
+     vmailmgr distribution.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,53 @@
+man_MANS = vmailmgr.7
+noinst_SGMLS = FAQ.sgml HOWTO.sgml
+noinst_TEXINFOS = configuration.texi vmailmgr-cgi.texi
+noinst_HTMLS = vmailmgr.html HOWTO.html FAQ.html NEWS.html \
+	configuration.html ChangeLog.html vmailmgr-cgi.html
+noinst_TXTS = HOWTO.txt FAQ.txt \
+	configuration.txt vmailmgr-cgi.txt protocol.txt \
+	record-format.txt
+noinst_PODS = vmailmgr.pod
+noinst_MISC = translation.ps
+EXTRA_DIST = ChangeLog-pre-vmailmgr ChangeLog-pre-0.70 \
+	changelog2html.pl news2html.pl \
+	YEAR2000 translation.fig translation.ps \
+	$(man_MANS) \
+	$(noinst_PODS) \
+	$(noinst_SGMLS) \
+	$(noinst_TEXINFOS) \
+	$(noinst_HTMLS) \
+	$(noinst_TXTS)
+CLEANFILES = $(noinst_HTMLS) $(man_MANS) \
+	HOWTO.txt FAQ.txt configuration.txt vmailmgr-cgi.txt
+
+TEXI2HTML = texi2html -monolithic -number
+CL2HTML	= perl changelog2html.pl
+NEWS2HTML = perl news2html.pl
+FIG2PS = fig2dev -L ps -c
+SGML2HTML = sgml2html --split=0
+SGML2TXT = sgml2txt
+
+all: $(noinst_HTMLS) $(noinst_TXTS) $(noinst_MISC)
+
+dist-hook:
+	touch $(distdir)/*.html
+	touch $(distdir)/*.txt
+	touch $(distdir)/*.[123456789]
+
+ChangeLog.html: ../ChangeLog
+	$(CL2HTML) $< >$@
+
+NEWS.html: ../NEWS
+	$(NEWS2HTML) $< >$@
+
+%.1: %.pod ../configure.in; $(POD2MAN) --section=1 $< >$@
+%.5: %.pod ../configure.in; $(POD2MAN) --section=5 $< >$@
+%.7: %.pod ../configure.in; $(POD2MAN) --section=7 $< >$@
+%.8: %.pod ../configure.in; $(POD2MAN) --section=8 $< >$@
+%.html: %.sgml; $(SGML2HTML) $<
+%.txt: %.sgml; $(SGML2TXT) $<
+%.html: %.pod; $(POD2HTML) $< >$@
+%.html: %.texi; $(TEXI2HTML) $< >$@
+%.txt: %.html; $(HTML2TXT) $< >$@
+
+%.ps: %.fig ../configure.in; $(FIG2PS) $< $@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,277 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+man_MANS = vmailmgr.7
+noinst_SGMLS = FAQ.sgml HOWTO.sgml
+noinst_TEXINFOS = configuration.texi vmailmgr-cgi.texi
+noinst_HTMLS = vmailmgr.html HOWTO.html FAQ.html NEWS.html 	configuration.html ChangeLog.html vmailmgr-cgi.html
+
+noinst_TXTS = HOWTO.txt FAQ.txt 	configuration.txt vmailmgr-cgi.txt protocol.txt 	record-format.txt
+
+noinst_PODS = vmailmgr.pod
+noinst_MISC = translation.ps
+EXTRA_DIST = ChangeLog-pre-vmailmgr ChangeLog-pre-0.70 	changelog2html.pl news2html.pl 	YEAR2000 translation.fig translation.ps 	$(man_MANS) 	$(noinst_PODS) 	$(noinst_SGMLS) 	$(noinst_TEXINFOS) 	$(noinst_HTMLS) 	$(noinst_TXTS)
+
+CLEANFILES = $(noinst_HTMLS) $(man_MANS) 	HOWTO.txt FAQ.txt configuration.txt vmailmgr-cgi.txt
+
+
+TEXI2HTML = texi2html -monolithic -number
+CL2HTML = perl changelog2html.pl
+NEWS2HTML = perl news2html.pl
+FIG2PS = fig2dev -L ps -c
+SGML2HTML = sgml2html --split=0
+SGML2TXT = sgml2txt
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+man7dir = $(mandir)/man7
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps doc/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+install-man7:
+	$(mkinstalldirs) $(DESTDIR)$(man7dir)
+	@list='$(man7_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.7*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man7dir)/$$inst"; \
+	  $(INSTALL_DATA) $$file $(DESTDIR)$(man7dir)/$$inst; \
+	done
+
+uninstall-man7:
+	@list='$(man7_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.7*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f $(DESTDIR)$(man7dir)/$$inst"; \
+	  rm -f $(DESTDIR)$(man7dir)/$$inst; \
+	done
+install-man: $(MANS)
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-man7
+uninstall-man:
+	@$(NORMAL_UNINSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-man7
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = doc
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-man
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(MANS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(mandir)/man7
+
+
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: install-man7 uninstall-man7 install-man uninstall-man tags \
+distdir info-am info dvi-am dvi check check-am installcheck-am \
+installcheck install-exec-am install-exec install-data-am install-data \
+install-am install uninstall-am uninstall all-redirect all-am all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+all: $(noinst_HTMLS) $(noinst_TXTS) $(noinst_MISC)
+
+dist-hook:
+	touch $(distdir)/*.html
+	touch $(distdir)/*.txt
+	touch $(distdir)/*.[123456789]
+
+ChangeLog.html: ../ChangeLog
+	$(CL2HTML) $< >$@
+
+NEWS.html: ../NEWS
+	$(NEWS2HTML) $< >$@
+
+%.1: %.pod ../configure.in; $(POD2MAN) --section=1 $< >$@
+%.5: %.pod ../configure.in; $(POD2MAN) --section=5 $< >$@
+%.7: %.pod ../configure.in; $(POD2MAN) --section=7 $< >$@
+%.8: %.pod ../configure.in; $(POD2MAN) --section=8 $< >$@
+%.html: %.sgml; $(SGML2HTML) $<
+%.txt: %.sgml; $(SGML2TXT) $<
+%.html: %.pod; $(POD2HTML) $< >$@
+%.html: %.texi; $(TEXI2HTML) $< >$@
+%.txt: %.html; $(HTML2TXT) $< >$@
+
+%.ps: %.fig ../configure.in; $(FIG2PS) $< $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/NEWS.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,576 @@
+<html>
+<head>
+<title>Release History</title>
+<body>
+<center><h1>Release History</h1></center>
+<hr>
+<h2>Changes in version 0.96.9</h2>
+<p>
+New Features:
+<ul>
+<li>vdeluser now has an option to prevent it from deleting users with a
+  mailbox.
+<li>All the Python CGI code has been dropped.  A stand-alone vpyadmin
+  package (to be release very shortly) will replace the Python CGIs.
+  Between this new interface and the PHP code, the C++ CGIs are
+  depricated and will be removed in a future version, unless somebody
+  violently objects.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>Cleaned up the vpwtable API.
+<li>New CLI documentation generator, should help keep the man pages and
+  the programs in sync.
+<li>Major overhaul to the Python library.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed error handling in vdeliver to properly handle file-system quota
+  errors.
+<li>Fixed a bug in the Courier IMAP authentication module that prevented
+  non-virtual users from authenticating.
+<li>The daemon now exits immediately if a SIGALRM or SIGPIPE is caught,
+  instead of completing the action.
+<li>Fixed a bug in autodetecting Python.  It should now work with any
+  version of make.
+</ul>
+<hr>
+<h2>Changes in version 0.96.8</h2>
+<p>
+New Features:
+<ul>
+<li>Added a quota checking program for use in vdeliver-predeliver.
+<li>The authvmailmgr Courier-IMAP auth module now executes
+  authvmailmgr-presetuid and authvmailmgr-postsetuid before and after
+  executing the setuid respectively, just like checkvpw.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>The daemon lookup command now returns all of the virtual user data,
+  not just the mailbox and forwarding.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed a typo in the vmailmgrd run script.
+<li>Fixed a bug in the daemon that would cause actions to be applied to
+  the default virtual user if the named virtual user did not exist.
+<li>Fixed a bug in the daemon that would allow disabled autoresponders to
+  be written to.
+<li>Fixed a bug in the subprogram execution code that would cause the
+  wrong exit status to be returned.
+<li>vdeliver now rewinds standard input before executing postdeliver.
+<li>The autoresponse daemon command will now read the disabled
+  autoresponse file if the enabled one does not exist.
+<li>Fixed note on setting up a domain in the HOWTO.
+<li>Fixed a bug in the fdbuf library.
+</ul>
+<hr>
+<h2>Changes in version 0.96.7</h2>
+<p>
+New Features:
+<ul>
+<li>Contains configure-time switchable support for GDBM virtual user tables.
+<li>Added a new utility, vpasswd2db, to convert a plain text password
+  table into whatever vpwtable format is configured.  This utility will
+  be much slower than vpasswd2cdb for CDB files (for now), so only use
+  it for other (ie GDBM) formats.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>Updated PHP code.
+<li>The daemon now relies on ucspi-unix to handle connections and forking
+  instead of doing it internally.
+<li>The autoresponse is written into a new subdirectory of the virtual
+  user's mailbox directory.  This makes it work better with the
+  autoresponder, which requires a directory to store temporary files in.
+<li>Reorganized the vpwtable code somewhat.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>The daemon now initializes its random number generator each time it
+  handles a command, which should make it generate different salts for
+  password hashes.
+<li>The python subdirectory no longer requires GNU make to build, and
+  should no longer build at all if Python cannot be located.
+</ul>
+<hr>
+<h2>Changes in version 0.96.6</h2>
+<p>
+New Features:
+<ul>
+<li>Added autoresponse command to daemon, modified from code submitted by
+  Mike Bell.  This allows the user to upload a autoresponse file to
+  their virtual mailbox, to be used by an autoresponder (not included).
+<li>Added autoresponse CGI written in Python, as well as updated Python
+  library code.
+<li>Updated PHP code from Mike Bell.
+<li>Replaced the FAQ and HOWTO documents with the revised ones by Dan
+  Kuykendall.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>The necessary parts of the Courier IMAP "authlib" library is now
+  included in this package.  The Courier IMAP authentication module is
+  now always built.
+<li>The Courier IMAP module is now part of the standard RPM.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed a problem with converting from old records that didn't set the
+  virtual user flags properly.
+<li>Fixed a problem with the virtual user creation time field not being
+  set properly.
+<li>Fixed a bug in vdeliver that would cause any error from the predeliver
+  script to be treated as a temporary failure.
+<li>Fixed a bug in the domain name lookup code that caused case sensitive
+  domain name comparisons.
+</ul>
+<hr>
+<h2>Changes in version 0.96.5</h2>
+<p>
+New Features:
+<ul>
+<li>Mailbox delivery can be temporarily disabled on a per-virtual-user
+  basis, through either the CGIs, command-line tools, or PHP, without
+  deleting the mailbox.
+<li>Account expiry is handled by the authentication tools and by vdeliver.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>The binary record format has changed to handle the new boolean flags.
+  Note that this new format is backwards compatible, so no conversion is
+  needed.
+<p>
+</ul>
+Bug Fixes: None
+<hr>
+<h2>Changes in version 0.96.4</h2>
+<p>
+New Features:
+<ul>
+<li>Added an upgrading section in the FAQ.
+<li>The command-line tools now have a "--quiet" option to suppress all
+  status messages.
+<li>Added a "vchforwards" CGI interface.
+<li>Modified the "vaddalias" CGI program to accept a comma-seperated list
+  of destinations.
+<li>Added some sample HTML pages for the CGIs.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>Minor updates to the mystring and fdbuf libraries.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed a problem that caused the Courier IMAP authentication module to
+  fail for users of the form "baseuser-virtuser".  It should work now.
+</ul>
+<hr>
+<h2>Changes in version 0.96.3</h2>
+<p>
+New Features: None
+<p>
+Internal Changes:
+<ul>
+<li>Removed the "include" directory.
+<li>Made vpwtable & vpwentry a seperate source directory.
+<li>Merged the "adduser", "addalias", and "addaliasp" daemon interfaces
+  into one new inteface named "adduser2".  The C++ CGIs and the PHP3
+  code has been modified to use the new interface.
+<p>
+</ul>
+Bug Fixes: None
+<hr>
+<h2>Changes in version 0.96.2</h2>
+<p>
+New Features:
+<ul>
+<li>Updated the FAQ, and added some new answers.
+<li>Added a Courier IMAP authentication module.  This module does not yet
+  work, unfortunately.
+<li>Tossed the existing non-functional PHP3 module and added a working one
+  (written in PHP3) from Mike Bell.
+<li>Modified vsetup to call programs before and after setting up the
+  domain.
+<li>Added new "vauthenticate" command.
+<li>Turned the small vaddalias program into a simple shell script.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>Moved the Python code into its own directory, like the PHP3 stuff.
+<li>Moved the checkvpw module into an "authenticate" directory.
+<li>Imported changes to the CLI library to make it behave more like the
+  standard getopt.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed some bugs in the Kerberos5 configuration handling.
+</ul>
+<hr>
+<h2>Changes in version 0.96.1</h2>
+<p>
+New Features:
+<ul>
+<li>Output of listvdomain CGI has changed slightly to reflect the change
+  in internal data structures.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>Changed listdomain daemon protocol to speed up domain listings and to
+  allow for more information (not yet present in the listdomain CGI).
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed bug in building Python code from input files with non-GNU make.
+</ul>
+<hr>
+<h2>Changes in version 0.96</h2>
+<p>
+New Features:
+<ul>
+<li>Record data format has been enhanced to add personal information,
+  simple quotas, and expiry information, plus other extra data.
+<li>Messages can now be delivered to both a mailbox and a list of
+  forwarding addresses at once.
+<li>Programs executed from checkvpw or vdeliver will have all the above
+  data set in environment variables.
+<li>listvdomain can now list only users, only aliases, or selected names.
+<li>The listvdomain CGI has improved formatting ability.
+<li>Preliminary support for Kerberos5 authentication.  Please tell me if
+  this works for you if you need this, as I can't test it myself.
+<li>New "vchattr" command to change a virtual user's attributes.
+<li>New "vchforwards" command to change the forwarding addresses of a
+  user.
+<li>Executable configuration settings are treated as executable files
+  rather than lists of statements to execute.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>Record parsing routines will read either record format but will write
+  out new record format.
+<li>Daemon command dispatching now requires seperate virtual domain and
+  virtual user arguments (all the CGIs do this anyways), as opposed to
+  allowing "baseuser-virtual".
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed non-portable increment statement in vconf2dir shell script, as
+  well as a couple of other bugs.
+<li>Fixed bug in vdeliver that would cause it to loop without sleeping
+  when it couldn't write to the output file.
+<p>
+</ul>
+NOTES:
+<ul>
+<li>I would consider this an unstable release.  Adding and deleting users,
+  delivery, and password checking have been tested, but little else.  I
+  just want to get this out.  There are so many big changes in this one
+  that there are bound to be unexpected bugs.
+<li>Despite the change in the record format, no password table upgrading
+  will be necessary, as this version can read in both new and old
+  records.
+<li>The "vaddalias" command has been superceeded by "vadduser -D".
+<li>The "vchalias" command has been replace with "vchforwards".
+<li>The "vdelalias" command has been removed since "vdeluser" does both
+  jobs.
+<li>Support for quota management and account expiry are not included yet.
+<li>The C++ CGIs are limited to adding aliases with a single forwarding
+  address.  The generic Python CGI can be used to create users with
+  multiple forwarding addresses.  I intend to remove most or all of the
+  C++ CGIs in favour of a more generic interface.
+</ul>
+<hr>
+<h2>Changes in version 0.95</h2>
+<p>
+New Features:
+<ul>
+<li>vdeliver now has a hook to execute a list of programs before and after
+  delivering an email.  See doc/configuration.* for full details.
+<li>checkvpw now has a hook to execute a list of programs before and after
+  changing its uid, and after executing the subprogram
+<li>The bulletins facility is now a standalone program called vpopbull.
+<li>There is a new program showvconfig which can list the configuration
+  information.
+<p>
+</ul>
+Internal Changes as above.
+<p>
+Bug Fixes:
+<ul>
+<li>The call to execl in vdeliver when calling qmail-queue was missing a
+  parameter.
+</ul>
+<hr>
+<h2>Changes in version 0.94</h2>
+<p>
+New Features:
+<ul>
+<li>vdeliver and checkvpw no longer call up to vmailmgrd to do user
+  lookups and authentication.  This makes them significantly faster,
+  since the daemon no longer does any useful memorization of any kind of
+  data (no password or virtualdomains caches, etc.), and the socket
+  connection and fork took significant amounts of time.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>The virtual user and virtual password table manipulation were moved
+  into a class interface.  This will be (once the password content
+  changes are integrated in the next couple of versions) the official
+  API target for building alternative database backends (like the much
+  requested MySQL interface).
+<li>Removed the "check" command from the daemon, since it's no longer
+  used.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>vdeliver still used a hard coded /var/qmail instead of
+  config->qmail_root().
+<p>
+</ul>
+NOTES:
+* You will no longer need to have vmailmgrd running to use checkvpw,
+<ul>
+  vdeliver, and the command-line tools.  You only need vmailmgrd (and
+  the vmailmgr-daemon RPM package) if you need to use the CGIs.
+</ul>
+<hr>
+<h2>Changes in version 0.93</h2>
+<p>
+New Features:
+<ul>
+<li>New configuration system, based on individual files per configuration
+  parameter rather than one big file.  Should be more extensable this
+  way, and has been benchmarked to be faster.  The configuration files
+  are documented in the configuration.{html,texi,txt} files.
+<li>New configuration system also set up to allow domain-local
+  configurations by putting a directory named ".vmailmgr" in the domain
+  directory.  This IS (unlike my last attempt) read properly by the
+  daemon and all the utilities and clients.  The daemon switches over to
+  checking for local configuration items immediately after determining
+  what user/domain is being handled.
+<li>A new "qmail-root" configuration parameter to allow for installations
+  where qmail is not installed in /var/qmail.
+<p>
+</ul>
+Internal Changes:
+<ul>
+<li>All the v* commands now do a chdir to $HOME before continuing.
+<li>A virtual domain class has been set up, and is used to reference each
+  domain through a user, with both a user-local and domain-local
+  configuration structure.  This will shortly be used to set up multiple
+  virtual domains per user.
+<li>Imported new and improved mystring and fdbuf libraries.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>The .qmail-default file is created with mode r--r--r-- to prevent
+  qmail problems with a writable delivery file in situations where the
+  umask is less restrictive than 022.
+<p>
+</ul>
+IMPORTANT NOTES:
+* This version uses a new configuration structure.  You *MUST* run the
+<ul>
+  included vconf2dir program.  The RPM tries to do this automatically.
+</ul>
+<hr>
+<h2>Changes in version 0.92.2</h2>
+<p>
+Bug Fixes:
+<ul>
+<li>Delivery to partially qualified aliases was broken again in a few hard
+  to trace cases by potentially changing one character in the domain
+  address.  Fixed by rewriting the envelope building code into something
+  simpler and more efficient.
+</ul>
+<hr>
+<h2>Changes in version 0.92.1</h2>
+<p>
+Bug Fixes:
+<ul>
+<li>Delivery to partially qualified aliases (such as the common 'root@')
+  caused vdeliver to either crash itself or to cause qmail-queue to
+  crash (since qmail-queue expects FQDN addresses).  This behavior has
+  been fixed to make such addresses use a domain name of the contents of
+  control/me.
+</ul>
+<hr>
+<h2>Changes in version 0.92</h2>
+<p>
+New Features:
+<ul>
+<li>Aliases can now have passwords.  See the man page for vaddalias or the
+  CGI documentation for details on how to create such an alias.  The
+  intended effect is that, once set up, a virtual user could "own" an
+  alias, for the purpose of changing its destination (or password, of
+  course).
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Delivery to aliases in vdeliver used to go through qmail-inject.  This
+  would cause qmail to reformat headers or even bounce the message.
+  vdeliver now sends aliases through qmail-queue, the same way that
+  qmail itself does it.
+</ul>
+<hr>
+<h2>Changes in version 0.91</h2>
+<p>
+New Features:
+<ul>
+<li>Command-line and CGI programs to change an alias (to avoid the delete,
+  recreate cycle).
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Always set the mode on created files to be read-write-only by owner.
+<p>
+</ul>
+Other Changes:
+<ul>
+<li>vdeliver now uses fdbuf instead of raw I/O to deliver content.
+<li>Changed the default default username from '*' to '+', to avoid
+  confusion when typing '*' at a shell prompt.
+<li>Command-line tools now count and report the number of errors
+  encountered and exit false if any errors occurred.
+</ul>
+<hr>
+<h2>Changes in version 0.90.2</h2>
+<p>
+New Features: None
+<p>
+Bug Fixes:
+<ul>
+<li>Fixed compile problem on systems lacking the O_SYNC definition.
+<li>Fixed compile problem on systems where perror is in stdio.h, and
+  stdio.h is not included through other includes.
+<p>
+</ul>
+NOTES: If you did not have a problem compiling 0.90 or 0.90.1, don't
+bother with this version.
+<hr>
+<h2>Changes in version 0.90.1</h2>
+<p>
+New Features: None
+<p>
+Bug Fixes:
+<ul>
+<li>Added definitions for MIN and MAX in md5-crypt.c if they aren't
+  defined by the included headers.
+<li>Removed the include of errnos.h in vpwentry_putpw.cc
+<p>
+</ul>
+NOTES: If you did not have a problem compiling 0.90, don't bother with
+this version.
+<hr>
+<h2>Changes in version 0.90</h2>
+<p>
+New Features:
+<ul>
+<li>Eliminated all dependance on any C++ library by incorporating my own
+  C++ I/O library.
+<li>Dropped the RSA MD5 library and incorporated the GNU MD5 code.
+<li>Added the GNU md5-crypt module which should provide compatibility with
+  all systems that do MD5-based passcodes.  The new code will read in
+  and authenticate against standard DES-crypted codes, the new standard
+  MD5-crypted '$1$' style codes, and my mistaken MD5 hashes (for
+  temporary backwards compatibility), and will write out the '$1$' style
+  MD5 codes.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Fixed a nearly invisible bug in the parsing of the configuration file
+  (it was too lenient in the syntax it allowed).
+<li>In the bulletin code, the timestamp file was named wrong
+  ("maildir/cur/.timestamp" instead of "maildir/.timestamp"), and it was
+  not created with a proper mode flag.
+<p>
+</ul>
+Other Changes:
+<ul>
+<li>This package is now distributed under the GPL.
+<li>The daemon will now not print out any "Accepted Connection" messages
+  unless the verbose flag is set.
+<li>Inverted the sense of the crypt flag in configure.  There is now a
+  "--enable-crypt" flag which causes the code to revert to only using
+  crypt for password encryption and comparison (the default is to use
+  the built-in md5-crypt module).
+<p>
+</ul>
+NOTES:
+<ul>
+<li>My plan to move from a fork-based daemon to a thread-based one is on
+  temporary hold until I can complete several other more important
+  reorganizations and cleanups, most importantly completing a generic DB
+  interface layer.
+</ul>
+<hr>
+<h2>Changes in version 0.89</h2>
+<p>
+New Features:
+<ul>
+<li>Changed the file format for the virtual password tables to using CDB
+  tables.
+<li>The daemon now forks immediately after accepting a connection,
+  allowing for greater concurrency in the POP3 server.
+<p>
+</ul>
+Bug Fixes:
+<ul>
+<li>Use a ".timestamp" file in a virtual user's maildir to determine the
+  last login time for bulletin delivery.
+<p>
+</ul>
+Other Changes:
+<ul>
+<li>Removed all the cache tables in the daemon.
+<li>Did a major reorganization of the libraries and header files.
+<p>
+</ul>
+IMPORTANT NOTES:
+* This package now uses an incompatible file format for the virtual
+<ul>
+  domain password tables.  You *MUST* run "vpasswd2cdb" in each
+  domain to convert your tables before starting the new daemon!
+</ul>
+<hr>
+<h2>Changes in version 0.88</h2>
+<p>
+New Features:
+<ul>
+<li>Long passwords are now supported using MD5 hashing to create the
+  encoded version.  The code will still read the older passwords but
+  will always write out MD5 hashes.
+<p>
+</ul>
+Bug Fixes:  None
+<p>
+Other Changes:
+<ul>
+<li>I am now finally using automake to build the package.
+</ul>
+<hr>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/YEAR2000	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,9 @@
+This package is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Having said that, wherever time is used within vmailmgr (verified with
+version 0.87 and later), it is treated as the number of seconds since
+the UNIX epoch.  It is not converted into or from a textual
+representation anywhere within the package and so is exempt from all
+year 2000 issues.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changelog2html.pl	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+$in_list = 0;
+
+print
+    "<html>\n",
+    "<head><title>ChangeLog</title></head>\n",
+    "<body>\n";
+while(<>) {
+    s/\s+$//;
+    s/^\s+//;
+    s/</\&lt;/g;
+    s/>/\&gt;/g;
+    if(/^\d+-\d+-\d+ /) {
+	print "</ul>\n</p>\n" if $in_list;
+	$in_list = 1;
+	print "<p>$_\n<ul>\n";
+    } elsif(s/^\* //) {
+	print "<li>$_\n";
+    } else {
+	print $_, "\n";
+    }
+}
+print "</ul>\n</p>\n" if $in_list;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/configuration.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,1027 @@
+<HTML>
+<HEAD>
+<!-- Created by texi2html 1.56k from configuration.texi on 14 September 2000 -->
+
+<TITLE>Vmailmgr Configuration Files</TITLE>
+</HEAD>
+<BODY>
+<H1>Vmailmgr Configuration Files</H1>
+<H2>14 September 2000</H2>
+<ADDRESS>Bruce Guenter</ADDRESS>
+<P>
+<P><HR><P>
+<H1>Table of Contents</H1>
+<UL>
+<LI><A NAME="TOC1" HREF="configuration.html#SEC1">1. General Information</A>
+<UL>
+<LI><A NAME="TOC2" HREF="configuration.html#SEC2">1.1 Search Order</A>
+<LI><A NAME="TOC3" HREF="configuration.html#SEC3">1.2 File Types</A>
+<LI><A NAME="TOC4" HREF="configuration.html#SEC4">1.3 Command Execution</A>
+</UL>
+<LI><A NAME="TOC5" HREF="configuration.html#SEC5">2. Configuration Files</A>
+<UL>
+<LI><A NAME="TOC6" HREF="configuration.html#SEC6">2.1 authvmailmgr-error</A>
+<LI><A NAME="TOC7" HREF="configuration.html#SEC7">2.2 authvmailmgr-loginfail</A>
+<LI><A NAME="TOC8" HREF="configuration.html#SEC8">2.3 authvmailmgr-postsetuid</A>
+<LI><A NAME="TOC9" HREF="configuration.html#SEC9">2.4 authvmailmgr-presetuid</A>
+<LI><A NAME="TOC10" HREF="configuration.html#SEC10">2.5 autoresponse-dir</A>
+<LI><A NAME="TOC11" HREF="configuration.html#SEC11">2.6 autoresponse-file</A>
+<LI><A NAME="TOC12" HREF="configuration.html#SEC12">2.7 bulletin-dir</A>
+<LI><A NAME="TOC13" HREF="configuration.html#SEC13">2.8 checkvpw-error</A>
+<LI><A NAME="TOC14" HREF="configuration.html#SEC14">2.9 checkvpw-loginfail</A>
+<LI><A NAME="TOC15" HREF="configuration.html#SEC15">2.10 checkvpw-postexec</A>
+<LI><A NAME="TOC16" HREF="configuration.html#SEC16">2.11 checkvpw-postsetuid</A>
+<LI><A NAME="TOC17" HREF="configuration.html#SEC17">2.12 checkvpw-presetuid</A>
+<LI><A NAME="TOC18" HREF="configuration.html#SEC18">2.13 default-expiry</A>
+<LI><A NAME="TOC19" HREF="configuration.html#SEC19">2.14 default-maildir</A>
+<LI><A NAME="TOC20" HREF="configuration.html#SEC20">2.15 default-msgcount</A>
+<LI><A NAME="TOC21" HREF="configuration.html#SEC21">2.16 default-msgsize</A>
+<LI><A NAME="TOC22" HREF="configuration.html#SEC22">2.17 default-hardquota</A>
+<LI><A NAME="TOC23" HREF="configuration.html#SEC23">2.18 default-softquota</A>
+<LI><A NAME="TOC24" HREF="configuration.html#SEC24">2.19 default-username</A>
+<LI><A NAME="TOC25" HREF="configuration.html#SEC25">2.20 error-maildir</A>
+<LI><A NAME="TOC26" HREF="configuration.html#SEC26">2.21 global-bulletin-dir</A>
+<LI><A NAME="TOC27" HREF="configuration.html#SEC27">2.22 maildir-arg-str</A>
+<LI><A NAME="TOC28" HREF="configuration.html#SEC28">2.23 password-file</A>
+<LI><A NAME="TOC29" HREF="configuration.html#SEC29">2.24 postmaster-aliases</A>
+<LI><A NAME="TOC30" HREF="configuration.html#SEC30">2.25 postmaster-email</A>
+<LI><A NAME="TOC31" HREF="configuration.html#SEC31">2.26 qmail-root</A>
+<LI><A NAME="TOC32" HREF="configuration.html#SEC32">2.27 separators</A>
+<LI><A NAME="TOC33" HREF="configuration.html#SEC33">2.28 socket-file</A>
+<LI><A NAME="TOC34" HREF="configuration.html#SEC34">2.29 user-dir</A>
+<LI><A NAME="TOC35" HREF="configuration.html#SEC35">2.30 user-dir-bits</A>
+<LI><A NAME="TOC36" HREF="configuration.html#SEC36">2.31 user-dir-slices</A>
+<LI><A NAME="TOC37" HREF="configuration.html#SEC37">2.32 vdeliver-postdeliver</A>
+<LI><A NAME="TOC38" HREF="configuration.html#SEC38">2.33 vdeliver-predeliver</A>
+<LI><A NAME="TOC39" HREF="configuration.html#SEC39">2.34 vsetup-pre</A>
+<LI><A NAME="TOC40" HREF="configuration.html#SEC40">2.35 vsetup-pre</A>
+</UL>
+</UL>
+<P><HR><P>
+
+
+<H1><A NAME="SEC1" HREF="configuration.html#TOC1">1. General Information</A></H1>
+
+
+
+<H2><A NAME="SEC2" HREF="configuration.html#TOC2">1.1 Search Order</A></H2>
+
+<P>
+The system will look for the configuration files listed below in one of
+the following three locations, in the order they are listed:
+
+<OL>
+<LI>The domain-local configuration directory
+
+<LI>The user-local configuration directory
+
+<LI>The global configuration directory
+
+</OL>
+
+<P>
+The global configuration directory is set to <TT>`/etc/vmailmgr'</TT> by
+default.
+The user-local and domain-local configuration directories (for now, one
+and the same) are a subdirectory, named <TT>`.vmailmgr'</TT> by default, of
+either the user's home directory or the domain subdirectory.  
+If a file matching the configuration name is found in one of the local
+directories, the search stops and it is not searched for in any
+higher up directories.
+
+
+
+
+<H2><A NAME="SEC3" HREF="configuration.html#TOC3">1.2 File Types</A></H2>
+
+<P>
+Each of the configuration files falls into one of the following types:
+
+
+<DL COMPACT>
+
+<DT>String
+<DD>
+A single line is read from this type and used as-is with no conversion.
+All data after the first line is ignored.
+
+<DT>Directory
+<DD>
+A single line is read from this type.
+If it does not have a trailing slash (<SAMP>`/'</SAMP>), one is appended.
+All data after the first line is ignored.
+
+<DT>Number
+<DD>
+A single line is read from this type and converted to an unsigned
+integer.
+If the conversion succeeds, the value is used.
+All data after the first line is ignored.
+
+<DT>List
+<DD>
+Each line of the file is read, stripped of leading and trailing
+whitespace, and treated as a separate value.
+Lines that contain only whitespace (ie blank lines) or lines beginning
+with a pound symbol (<SAMP>`#'</SAMP>) are ignored.
+
+<DT>Executable
+<DD>
+If the execute bits on the file are set, it is treated as an executable
+file and is executed with no interpretation by vmailmgr.
+The the Command Execution section below for details.
+
+</DL>
+
+<P>
+All lines are stripped of any leading or trailing white space.
+
+
+<P>
+Configuration files marked as <SAMP>`(global only)'</SAMP> are read
+before any user-level processing occurrs, and so are not functional in
+the user-level configuration.
+
+
+
+
+<H2><A NAME="SEC4" HREF="configuration.html#TOC4">1.3 Command Execution</A></H2>
+
+<P>
+The following rules apply to executing a single command or a list of
+commands.
+
+
+<P>
+The executables are searched in reverse order of the configuration
+files.
+That is, the global setting is used first, and then the local settings.
+If the named file either does not exist in a directory or is not
+executable, that directory is skipped.
+
+
+<P>
+A command exit code of <SAMP>`99'</SAMP> indicates that the command completed
+successfully but no further commands should be executed.
+All other non-zero exit codes are treated as an error and will cause the
+invoking program to stop with the same error code.
+For <TT>`vdeliver'</TT>, an error exit of 111 will be passed up to qmail as a
+temporary error, and an error exit of 100 will be passed up as a
+permanent failure.
+See the <TT>`qmail-command'</TT> man page for full details on delivery error
+codes.
+For <TT>`checkvpw'</TT>, any non-zero exit code (except as described above)
+will cause authentication to fail.
+
+
+<P>
+The following environment variables will be set (where applicable):
+
+
+<DL COMPACT>
+
+<DT><SAMP>`HOME'</SAMP>
+<DD>
+The home directory of the real user.
+<DT><SAMP>`MAILDIR'</SAMP>
+<DD>
+The mail directory of the real or virtual user.
+<DT><SAMP>`USER'</SAMP>
+<DD>
+The real user's name.
+<DT><SAMP>`VUSER'</SAMP>
+<DD>
+The virtual user's name.
+For base user logins, this is blank, and all the following items
+prefixed with <SAMP>`VUSER_'</SAMP> are not set.
+<DT><SAMP>`VUSER_CTIME'</SAMP>
+<DD>
+The virtual user's creation time (or "0" if unknown).
+<DT><SAMP>`VUSER_EXPIRY'</SAMP>
+<DD>
+The virtual user's expiry time (or "-" if not applicable).
+<DT><SAMP>`VUSER_HARDQUOTA'</SAMP>
+<DD>
+The virtual user's total size hard quota (in bytes, or "-" if not applicable).
+<DT><SAMP>`VUSER_MSGCOUNT'</SAMP>
+<DD>
+The virtual user's message count limit (or "-" if not applicable).
+<DT><SAMP>`VUSER_MSGSIZE'</SAMP>
+<DD>
+The virtual user's message size limit (or "-" if not applicable).
+<DT><SAMP>`VUSER_PERSONAL'</SAMP>
+<DD>
+The virtual user's personal data.
+<DT><SAMP>`VUSER_SOFTQUOTA'</SAMP>
+<DD>
+The virtual user's total size soft quota (in bytes, or "-" if not applicable).
+</DL>
+
+
+
+<H1><A NAME="SEC5" HREF="configuration.html#TOC5">2. Configuration Files</A></H1>
+
+<P>
+Each of the following sections identifies a single configuration file
+
+
+
+
+<H2><A NAME="SEC6" HREF="configuration.html#TOC6">2.1 authvmailmgr-error</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+authvmailmgr
+<DT><STRONG>Description</STRONG>
+<DD>
+This is executed by authvmailmgr if any error occurrs other than those
+caught by <TT>`authvmailmgr-loginfail'</TT> below.
+The environment variable <CODE>AUTHVMAILMGR_ERROR</CODE> will contain an error
+message.
+This can be used to output logging messages about errors in authvmailmgr.
+</DL>
+
+
+
+<H2><A NAME="SEC7" HREF="configuration.html#TOC7">2.2 authvmailmgr-loginfail</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+authvmailmgr
+<DT><STRONG>Description</STRONG>
+<DD>
+This is executed by authvmailmgr if the user's login fails.
+The environment variable <CODE>AUTHVMAILMGR_ERROR</CODE> will contain an error
+message.
+The environment variable <CODE>VUSER</CODE> will be set to the virtual user
+name if it has been determined.
+This can be used to output logging messages about login failures or to
+throttle hackers.
+</DL>
+
+
+
+<H2><A NAME="SEC8" HREF="configuration.html#TOC8">2.3 authvmailmgr-postsetuid</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+@samp {vpopbull}
+<DT><STRONG>Used By</STRONG>
+<DD>
+authvmailmgr
+<DT><STRONG>Description</STRONG>
+<DD>
+This is executed by authvmailmgr after a user is successfully authenticated.
+</DL>
+
+
+
+<H2><A NAME="SEC9" HREF="configuration.html#TOC9">2.4 authvmailmgr-presetuid</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+authvmailmgr
+<DT><STRONG>Description</STRONG>
+<DD>
+This list is executed by authvmailmgr before changing user away from root,
+and before authenticating a virtual user.
+Note: The environment variable <SAMP>`MAILDIR'</SAMP> is not set since the
+virtual user has not yet been authenticated, or even looked up
+at this point.
+For the same reason, <SAMP>`VUSER'</SAMP> is not authenticated and is under
+complete control of the invoking user.
+</DL>
+
+
+
+<H2><A NAME="SEC10" HREF="configuration.html#TOC10">2.5 autoresponse-dir</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+directory
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`autoresponse'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd, autoresponder script
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the subdirectory of the virtual user directory in which all
+autoresponse data is stored.
+</DL>
+
+
+
+<H2><A NAME="SEC11" HREF="configuration.html#TOC11">2.6 autoresponse-file</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`message.txt'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd, autoresponder script
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the file name within the autoresponse directory that contains
+the autoresponse message.
+</DL>
+
+
+
+<H2><A NAME="SEC12" HREF="configuration.html#TOC12">2.7 bulletin-dir</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+directory
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`bulletins'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the subdirectory of the domain directory in which bulletins
+local to a domain are stored.
+</DL>
+
+
+
+<H2><A NAME="SEC13" HREF="configuration.html#TOC13">2.8 checkvpw-error</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+This is executed by checkvpw if any error occurrs other than those
+caught by <TT>`checkvpw-loginfail'</TT> below.
+The environment variable <CODE>CHECKVPW_ERROR</CODE> will contain an error
+message.
+This can be used to output logging messages about errors in checkvpw.
+</DL>
+
+
+
+<H2><A NAME="SEC14" HREF="configuration.html#TOC14">2.9 checkvpw-loginfail</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+This is executed by checkvpw if the user's login fails.
+The environment variable <CODE>CHECKVPW_ERROR</CODE> will contain an error
+message.
+The environment variable <CODE>VUSER</CODE> will be set to the virtual user
+name if it has been determined.
+This can be used to output logging messages about login failures or to
+throttle hackers.
+</DL>
+
+
+
+<H2><A NAME="SEC15" HREF="configuration.html#TOC15">2.10 checkvpw-postexec</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+This is executed by checkvpw after the subcommand successfully completes.
+</DL>
+
+
+
+<H2><A NAME="SEC16" HREF="configuration.html#TOC16">2.11 checkvpw-postsetuid</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+@samp {vpopbull}
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+This is executed by checkvpw after a user is successfully authenticated.
+</DL>
+
+
+
+<H2><A NAME="SEC17" HREF="configuration.html#TOC17">2.12 checkvpw-presetuid</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+This list is executed by checkvpw before changing user away from root,
+and before authenticating a virtual user.
+Note: The environment variable <SAMP>`MAILDIR'</SAMP> is not set since the
+virtual user has not yet been authenticated, or even looked up
+at this point.
+For the same reason, <SAMP>`VUSER'</SAMP> is not authenticated and is under
+complete control of the invoking user.
+</DL>
+
+
+
+<H2><A NAME="SEC18" HREF="configuration.html#TOC18">2.13 default-expiry</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+number
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`-1'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vadduser
+<DT><STRONG>Description</STRONG>
+<DD>
+Sets the default expiry value for newly created users.
+Negative values indicate no expiry.
+</DL>
+
+
+
+<H2><A NAME="SEC19" HREF="configuration.html#TOC19">2.14 default-maildir</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+directory
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`Maildir'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+Sets the name of the directory to be used as a non-virtual user's maildir.
+</DL>
+
+
+
+<H2><A NAME="SEC20" HREF="configuration.html#TOC20">2.15 default-msgcount</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+number
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`-1'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vadduser
+<DT><STRONG>Description</STRONG>
+<DD>
+Sets the default message count limit.
+</DL>
+
+
+
+<H2><A NAME="SEC21" HREF="configuration.html#TOC21">2.16 default-msgsize</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+number
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`-1'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vadduser
+<DT><STRONG>Description</STRONG>
+<DD>
+Sets the default message size limit, in bytes.
+</DL>
+
+
+
+<H2><A NAME="SEC22" HREF="configuration.html#TOC22">2.17 default-hardquota</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+number
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`-1'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vadduser
+<DT><STRONG>Description</STRONG>
+<DD>
+Sets the default hard quota, in bytes.
+</DL>
+
+
+
+<H2><A NAME="SEC23" HREF="configuration.html#TOC23">2.18 default-softquota</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+number
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`-1'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vadduser
+<DT><STRONG>Description</STRONG>
+<DD>
+Sets the default soft quota, in bytes.
+</DL>
+
+
+
+<H2><A NAME="SEC24" HREF="configuration.html#TOC24">2.19 default-username</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`+'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the name of the virtual user to be looked up if a lookup of
+another virtual user fails.
+</DL>
+
+
+
+<H2><A NAME="SEC25" HREF="configuration.html#TOC25">2.20 error-maildir</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+directory
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`/var/lib/vmailmgr/error-maildir'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+Specifies the path of a read-only maildir containing a message to be
+sent to the user when the maildir corresponding to that user does not
+exist.
+</DL>
+
+
+
+<H2><A NAME="SEC26" HREF="configuration.html#TOC26">2.21 global-bulletin-dir</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+directory
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`/var/spool/bulletins'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies a site-wide bulletin directory.
+</DL>
+
+
+
+<H2><A NAME="SEC27" HREF="configuration.html#TOC27">2.22 maildir-arg-str</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`maildir'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw (global only)
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the string to search for when attempting to identify the
+maildir argument on the command line to checkvpw.
+</DL>
+
+
+
+<H2><A NAME="SEC28" HREF="configuration.html#TOC28">2.23 password-file</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`passwd'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd and command-line programs
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the file that contains user names, passwords, and
+destinations for a virtual domain.
+Note that this has nothing to do with "real" users, for which the
+password file is determined by the system libraries.
+</DL>
+
+
+
+<H2><A NAME="SEC29" HREF="configuration.html#TOC29">2.24 postmaster-aliases</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+list
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`mailer-daemon'</SAMP>
+<SAMP>`postmaster'</SAMP>
+<SAMP>`root'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vsetup
+<DT><STRONG>Description</STRONG>
+<DD>
+A list of aliases to the postmaster email address to set
+up when creating a new virtual domain with the vsetup command.
+This should <EM>always</EM> contain both <SAMP>`postmaster'</SAMP> and
+<SAMP>`mailer-daemon'</SAMP> (required by the RFCs), and should usually contain
+<SAMP>`root'</SAMP>.
+</DL>
+
+
+
+<H2><A NAME="SEC30" HREF="configuration.html#TOC30">2.25 postmaster-email</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`postmaster@'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vsetup
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the email address of the entity responsible
+for the administration of the (virtual) host when building the
+postmaster aliases above.
+If this value ends with a trailing <SAMP>`@'</SAMP>, the value of
+<TT>`/var/qmail/control/me'</TT> is filled in for the host name.
+If no <SAMP>`@'</SAMP> is present, the current virtual host name
+is filled in by vdeliver.
+If this is set to <SAMP>`postmaster'</SAMP>, a mail loop
+will result and all mail to this address will bounce.
+</DL>
+
+
+
+<H2><A NAME="SEC31" HREF="configuration.html#TOC31">2.26 qmail-root</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`/var/qmail'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw, vdeliver, vmailmgrd
+<DT><STRONG>Description</STRONG>
+<DD>
+Specifies the location of the base directory of your qmail install.
+Set this to whatever you put into <TT>`conf-home'</TT> when you built and
+installed qmail.
+</DL>
+
+
+
+<H2><A NAME="SEC32" HREF="configuration.html#TOC32">2.27 separators</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`@:'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+checkvpw (global only)
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the set of valid separators within a user login name between
+the virtual user name and virtual domain name when logging in via
+checkvpw.
+For example, if separators contains <SAMP>`@:'</SAMP> then <SAMP>`user@domain'</SAMP> and
+<SAMP>`user:domain'</SAMP> are equivalent POP mailbox names.
+</DL>
+
+
+
+<H2><A NAME="SEC33" HREF="configuration.html#TOC33">2.28 socket-file</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+string
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`/tmp/.vmailmgrd'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd, checkvpw, vdeliver, and the CGI programs
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the file name of the local socket used to
+communicate between the vmailmgr daemon and the other programs.
+<EM>Warning:</EM> Changing this in the local configuration directories
+will cause vdeliver to fail.
+</DL>
+
+
+
+<H2><A NAME="SEC34" HREF="configuration.html#TOC34">2.29 user-dir</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+directory
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`users'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd and command-line programs
+<DT><STRONG>Description</STRONG>
+<DD>
+Identifies the subdirectory from the virtual domain directory in which a
+virtual user's maildir will be created.
+Since this maildir is recorded in the password table, it does not have
+to be the same for each user within a domain.
+This is prefixed with <SAMP>`./'</SAMP> before it is used in the password table.
+</DL>
+
+
+
+<H2><A NAME="SEC35" HREF="configuration.html#TOC35">2.30 user-dir-bits</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`0'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd and command-line programs when creating new users.
+<DT><STRONG>Description</STRONG>
+<DD>
+See section <A HREF="configuration.html#SEC36">2.31 user-dir-slices</A>
+</DL>
+
+
+
+<H2><A NAME="SEC36" HREF="configuration.html#TOC36">2.31 user-dir-slices</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+<DT><STRONG>Default</STRONG>
+<DD>
+<SAMP>`0'</SAMP>
+<DT><STRONG>Used By</STRONG>
+<DD>
+vmailmgrd and command-line programs when creating new users.
+<DT><STRONG>Description</STRONG>
+<DD>
+<TT>`user-dir-bits'</TT> and <TT>`user-dir-slices'</TT> work together.  When creating a
+new user directory name, a hash code is generated on the name of the
+new user.  This hash code is split into <TT>`user-dir-slices'</TT> pieces, each
+<TT>`user-dir-bits'</TT> bits long.  Each of these pieces is translated to an
+ASCII string by converting the binary code to hexadecimal.  The
+resulting user directory name is then composed of:
+
+<UL>
+<LI>the base users directory, followed by a <SAMP>`/'</SAMP>
+
+<LI>each of the string pieces, each followed by a <SAMP>`/'</SAMP>
+
+<LI>the user's name
+
+</UL>
+
+For example, with <TT>`user-dir-bits'</TT> set to 6 and
+<TT>`user-dir-slices'</TT> set to 1, a user
+named <SAMP>`c'</SAMP> maps to a directory name of <SAMP>`users/2f/c/'</SAMP>.
+</DL>
+
+
+
+<H2><A NAME="SEC37" HREF="configuration.html#TOC37">2.32 vdeliver-postdeliver</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+vdeliver
+<DT><STRONG>Description</STRONG>
+<DD>
+This list is executed after the delivery is successfully
+completed.
+Since vdeliver expects <SAMP>`USER'</SAMP> and <SAMP>`HOME'</SAMP> to be set, it does
+not set them itself.
+If the command returns with an error code, a warning is printed, but
+delivery does not fail, as failure would lead to duplicates.
+</DL>
+
+
+
+<H2><A NAME="SEC38" HREF="configuration.html#TOC38">2.33 vdeliver-predeliver</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+vdeliver
+<DT><STRONG>Description</STRONG>
+<DD>
+This list is executed before the delivery is attempted, but
+after the virtual user information is looked up.
+Since vdeliver expects <SAMP>`USER'</SAMP> and <SAMP>`HOME'</SAMP> to be set, it does
+not set them itself.
+</DL>
+
+
+
+<H2><A NAME="SEC39" HREF="configuration.html#TOC39">2.34 vsetup-pre</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+vsetup
+<DT><STRONG>Description</STRONG>
+<DD>
+This list is executed after the vsetup command has sucessfully done
+everything else.
+</DL>
+
+
+
+<H2><A NAME="SEC40" HREF="configuration.html#TOC40">2.35 vsetup-pre</A></H2>
+
+<DL COMPACT>
+
+<DT><STRONG>Type</STRONG>
+<DD>
+executable
+<DT><STRONG>Default</STRONG>
+<DD>
+Empty
+<DT><STRONG>Used By</STRONG>
+<DD>
+vsetup
+<DT><STRONG>Description</STRONG>
+<DD>
+This list is executed before the vsetup command makes any changes.
+</DL>
+
+<P><HR><P>
+This document was generated on 14 September 2000 using
+<A HREF="http://wwwinfo.cern.ch/dis/texi2html/">texi2html</A>&nbsp;1.56k.
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/configuration.texi	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,821 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename configuration.info
+@settitle Vmailmgr Configuration Files
+@setchapternewpage off
+@paragraphindent 5
+@footnotestyle end
+@c %**end of header
+
+@ifinfo
+Copyright @copyright{} 1998 Bruce Guenter
+@end ifinfo
+
+@titlepage
+@title Vmailmgr Configuration Files
+@author Bruce Guenter
+@subtitle @today{}
+@end titlepage
+
+@node Top, General Information, (dir), (dir)
+
+@menu
+* General Information::         
+* Configuration Files::         
+@end menu
+
+@c ****************************************************************************
+@node General Information, Configuration Files, Top, Top
+@chapter General Information
+
+@menu
+* Search Order::                
+* File Types::                  
+* Command Execution::           
+@end menu
+
+@c ============================================================================
+@node Search Order, File Types, General Information, General Information
+@section Search Order
+
+The system will look for the configuration files listed below in one of
+the following three locations, in the order they are listed:
+@enumerate
+@item The domain-local configuration directory
+@item The user-local configuration directory
+@item The global configuration directory
+@end enumerate
+The global configuration directory is set to @file{/etc/vmailmgr} by
+default.
+The user-local and domain-local configuration directories (for now, one
+and the same) are a subdirectory, named @file{.vmailmgr} by default, of
+either the user's home directory or the domain subdirectory.  
+If a file matching the configuration name is found in one of the local
+directories, the search stops and it is not searched for in any
+higher up directories.
+
+@c ============================================================================
+@node File Types, Command Execution, Search Order, General Information
+@section File Types
+
+Each of the configuration files falls into one of the following types:
+
+@table @asis
+
+@item String
+
+A single line is read from this type and used as-is with no conversion.
+All data after the first line is ignored.
+
+@item Directory
+
+A single line is read from this type.
+If it does not have a trailing slash (@samp{/}), one is appended.
+All data after the first line is ignored.
+
+@item Number
+
+A single line is read from this type and converted to an unsigned
+integer.
+If the conversion succeeds, the value is used.
+All data after the first line is ignored.
+
+@item List
+
+Each line of the file is read, stripped of leading and trailing
+whitespace, and treated as a separate value.
+Lines that contain only whitespace (ie blank lines) or lines beginning
+with a pound symbol (@samp{#}) are ignored.
+
+@item Executable
+
+If the execute bits on the file are set, it is treated as an executable
+file and is executed with no interpretation by vmailmgr.
+The the Command Execution section below for details.
+
+@end table
+
+All lines are stripped of any leading or trailing white space.
+
+Configuration files marked as @samp{(global only)} are read
+before any user-level processing occurrs, and so are not functional in
+the user-level configuration.
+
+@c ============================================================================
+@node Command Execution,  , File Types, General Information
+@section Command Execution
+
+The following rules apply to executing a single command or a list of
+commands.
+
+The executables are searched in reverse order of the configuration
+files.
+That is, the global setting is used first, and then the local settings.
+If the named file either does not exist in a directory or is not
+executable, that directory is skipped.
+
+A command exit code of @samp{99} indicates that the command completed
+successfully but no further commands should be executed.
+All other non-zero exit codes are treated as an error and will cause the
+invoking program to stop with the same error code.
+For @file{vdeliver}, an error exit of 111 will be passed up to qmail as a
+temporary error, and an error exit of 100 will be passed up as a
+permanent failure.
+See the @file{qmail-command} man page for full details on delivery error
+codes.
+For @file{checkvpw}, any non-zero exit code (except as described above)
+will cause authentication to fail.
+
+The following environment variables will be set (where applicable):
+
+@table @samp
+@item HOME
+The home directory of the real user.
+@item MAILDIR
+The mail directory of the real or virtual user.
+@item USER
+The real user's name.
+@item VUSER
+The virtual user's name.
+For base user logins, this is blank, and all the following items
+prefixed with @samp{VUSER_} are not set.
+@item VUSER_CTIME
+The virtual user's creation time (or "0" if unknown).
+@item VUSER_EXPIRY
+The virtual user's expiry time (or "-" if not applicable).
+@item VUSER_HARDQUOTA
+The virtual user's total size hard quota (in bytes, or "-" if not applicable).
+@item VUSER_MSGCOUNT
+The virtual user's message count limit (or "-" if not applicable).
+@item VUSER_MSGSIZE
+The virtual user's message size limit (or "-" if not applicable).
+@item VUSER_PERSONAL
+The virtual user's personal data.
+@item VUSER_SOFTQUOTA
+The virtual user's total size soft quota (in bytes, or "-" if not applicable).
+@end table
+
+@c ****************************************************************************
+@node Configuration Files,  , General Information, Top
+@chapter Configuration Files
+
+Each of the following sections identifies a single configuration file
+
+@menu
+* authvmailmgr-error::          
+* authvmailmgr-loginfail::      
+* authvmailmgr-postsetuid::     
+* authvmailmgr-presetuid::      
+* autoresponse-dir::            
+* autoresponse-file::           
+* bulletin-dir::                
+* checkvpw-error::              
+* checkvpw-loginfail::          
+* checkvpw-postexec::           
+* checkvpw-postsetuid::         
+* checkvpw-presetuid::          
+* default-expiry::              
+* default-maildir::             
+* default-msgcount::            
+* default-msgsize::             
+* default-hardquota::           
+* default-softquota::           
+* default-username::            
+* error-maildir::               
+* global-bulletin-dir::         
+* maildir-arg-str::             
+* password-file::               
+* postmaster-aliases::          
+* postmaster-email::            
+* qmail-root::                  
+* separators::                  
+* socket-file::                 
+* user-dir::                    
+* user-dir-bits::               
+* user-dir-slices::             
+* vdeliver-postdeliver::        
+* vdeliver-predeliver::         
+* vsetup-post::                 
+* vsetup-pre::                  
+@end menu
+
+@c ============================================================================
+@node authvmailmgr-error, authvmailmgr-loginfail, Configuration Files, Configuration Files
+@section authvmailmgr-error
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+authvmailmgr
+@item Description
+This is executed by authvmailmgr if any error occurrs other than those
+caught by @file{authvmailmgr-loginfail} below.
+The environment variable @code{AUTHVMAILMGR_ERROR} will contain an error
+message.
+This can be used to output logging messages about errors in authvmailmgr.
+@end table
+
+@c ============================================================================
+@node authvmailmgr-loginfail, authvmailmgr-postsetuid, authvmailmgr-error, Configuration Files
+@section authvmailmgr-loginfail
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+authvmailmgr
+@item Description
+This is executed by authvmailmgr if the user's login fails.
+The environment variable @code{AUTHVMAILMGR_ERROR} will contain an error
+message.
+The environment variable @code{VUSER} will be set to the virtual user
+name if it has been determined.
+This can be used to output logging messages about login failures or to
+throttle hackers.
+@end table
+
+@c ============================================================================
+@node authvmailmgr-postsetuid, authvmailmgr-presetuid, authvmailmgr-loginfail, Configuration Files
+@section authvmailmgr-postsetuid
+
+@table @strong
+@item Type
+executable
+@item Default
+@samp {vpopbull}
+@item Used By
+authvmailmgr
+@item Description
+This is executed by authvmailmgr after a user is successfully authenticated.
+@end table
+
+@c ============================================================================
+@node authvmailmgr-presetuid, autoresponse-dir, authvmailmgr-postsetuid, Configuration Files
+@section authvmailmgr-presetuid
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+authvmailmgr
+@item Description
+This list is executed by authvmailmgr before changing user away from root,
+and before authenticating a virtual user.
+Note: The environment variable @samp{MAILDIR} is not set since the
+virtual user has not yet been authenticated, or even looked up
+at this point.
+For the same reason, @samp{VUSER} is not authenticated and is under
+complete control of the invoking user.
+@end table
+
+@c ============================================================================
+@node autoresponse-dir, autoresponse-file, authvmailmgr-presetuid, Configuration Files
+@section autoresponse-dir
+
+@table @strong
+@item Type
+directory
+@item Default
+@samp{autoresponse}
+@item Used By
+vmailmgrd, autoresponder script
+@item Description
+Identifies the subdirectory of the virtual user directory in which all
+autoresponse data is stored.
+@end table
+
+@c ============================================================================
+@node autoresponse-file, bulletin-dir, autoresponse-dir, Configuration Files
+@section autoresponse-file
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{message.txt}
+@item Used By
+vmailmgrd, autoresponder script
+@item Description
+Identifies the file name within the autoresponse directory that contains
+the autoresponse message.
+@end table
+
+@c ============================================================================
+@node bulletin-dir, checkvpw-error, autoresponse-file, Configuration Files
+@section bulletin-dir
+
+@table @strong
+@item Type
+directory
+@item Default
+@samp{bulletins}
+@item Used By
+checkvpw
+@item Description
+Identifies the subdirectory of the domain directory in which bulletins
+local to a domain are stored.
+@end table
+
+@c ============================================================================
+@node checkvpw-error, checkvpw-loginfail, bulletin-dir, Configuration Files
+@section checkvpw-error
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+checkvpw
+@item Description
+This is executed by checkvpw if any error occurrs other than those
+caught by @file{checkvpw-loginfail} below.
+The environment variable @code{CHECKVPW_ERROR} will contain an error
+message.
+This can be used to output logging messages about errors in checkvpw.
+@end table
+
+@c ============================================================================
+@node checkvpw-loginfail, checkvpw-postexec, checkvpw-error, Configuration Files
+@section checkvpw-loginfail
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+checkvpw
+@item Description
+This is executed by checkvpw if the user's login fails.
+The environment variable @code{CHECKVPW_ERROR} will contain an error
+message.
+The environment variable @code{VUSER} will be set to the virtual user
+name if it has been determined.
+This can be used to output logging messages about login failures or to
+throttle hackers.
+@end table
+
+@c ============================================================================
+@node checkvpw-postexec, checkvpw-postsetuid, checkvpw-loginfail, Configuration Files
+@section checkvpw-postexec
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+checkvpw
+@item Description
+This is executed by checkvpw after the subcommand successfully completes.
+@end table
+
+@c ============================================================================
+@node checkvpw-postsetuid, checkvpw-presetuid, checkvpw-postexec, Configuration Files
+@section checkvpw-postsetuid
+
+@table @strong
+@item Type
+executable
+@item Default
+@samp {vpopbull}
+@item Used By
+checkvpw
+@item Description
+This is executed by checkvpw after a user is successfully authenticated.
+@end table
+
+@c ============================================================================
+@node checkvpw-presetuid, default-expiry, checkvpw-postsetuid, Configuration Files
+@section checkvpw-presetuid
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+checkvpw
+@item Description
+This list is executed by checkvpw before changing user away from root,
+and before authenticating a virtual user.
+Note: The environment variable @samp{MAILDIR} is not set since the
+virtual user has not yet been authenticated, or even looked up
+at this point.
+For the same reason, @samp{VUSER} is not authenticated and is under
+complete control of the invoking user.
+@end table
+
+@c ============================================================================
+@node  default-expiry, default-maildir, checkvpw-presetuid, Configuration Files
+@section default-expiry
+
+@table @strong
+@item Type
+number
+@item Default
+@samp{-1}
+@item Used By
+vadduser
+@item Description
+Sets the default expiry value for newly created users.
+Negative values indicate no expiry.
+@end table
+
+@c ============================================================================
+@node  default-maildir, default-msgcount, default-expiry, Configuration Files
+@section default-maildir
+
+@table @strong
+@item Type
+directory
+@item Default
+@samp{Maildir}
+@item Used By
+checkvpw
+@item Description
+Sets the name of the directory to be used as a non-virtual user's maildir.
+@end table
+
+@c ============================================================================
+@node  default-msgcount, default-msgsize, default-maildir, Configuration Files
+@section default-msgcount
+
+@table @strong
+@item Type
+number
+@item Default
+@samp{-1}
+@item Used By
+vadduser
+@item Description
+Sets the default message count limit.
+@end table
+
+@c ============================================================================
+@node  default-msgsize, default-hardquota, default-msgcount, Configuration Files
+@section default-msgsize
+
+@table @strong
+@item Type
+number
+@item Default
+@samp{-1}
+@item Used By
+vadduser
+@item Description
+Sets the default message size limit, in bytes.
+@end table
+
+@c ============================================================================
+@node default-hardquota, default-softquota, default-msgsize, Configuration Files
+@section default-hardquota
+
+@table @strong
+@item Type
+number
+@item Default
+@samp{-1}
+@item Used By
+vadduser
+@item Description
+Sets the default hard quota, in bytes.
+@end table
+
+@c ============================================================================
+@node default-softquota, default-username, default-hardquota, Configuration Files
+@section default-softquota
+
+@table @strong
+@item Type
+number
+@item Default
+@samp{-1}
+@item Used By
+vadduser
+@item Description
+Sets the default soft quota, in bytes.
+@end table
+
+@c ============================================================================
+@node default-username, error-maildir, default-softquota, Configuration Files
+@section default-username
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{+}
+@item Used By
+vmailmgrd
+@item Description
+Identifies the name of the virtual user to be looked up if a lookup of
+another virtual user fails.
+@end table
+
+@c ============================================================================
+@node error-maildir, global-bulletin-dir, default-username, Configuration Files
+@section error-maildir
+
+@table @strong
+@item Type
+directory
+@item Default
+@samp{/var/lib/vmailmgr/error-maildir}
+@item Used By
+checkvpw
+@item Description
+Specifies the path of a read-only maildir containing a message to be
+sent to the user when the maildir corresponding to that user does not
+exist.
+@end table
+
+@c ============================================================================
+@node global-bulletin-dir, maildir-arg-str, error-maildir, Configuration Files
+@section global-bulletin-dir
+
+@table @strong
+@item Type
+directory
+@item Default
+@samp{/var/spool/bulletins}
+@item Used By
+checkvpw
+@item Description
+Identifies a site-wide bulletin directory.
+@end table
+
+@c ============================================================================
+@node maildir-arg-str, password-file, global-bulletin-dir, Configuration Files
+@section maildir-arg-str
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{maildir}
+@item Used By
+checkvpw (global only)
+@item Description
+Identifies the string to search for when attempting to identify the
+maildir argument on the command line to checkvpw.
+@end table
+
+@c ============================================================================
+@node password-file, postmaster-aliases, maildir-arg-str, Configuration Files
+@section password-file
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{passwd}
+@item Used By
+vmailmgrd and command-line programs
+@item Description
+Identifies the file that contains user names, passwords, and
+destinations for a virtual domain.
+Note that this has nothing to do with "real" users, for which the
+password file is determined by the system libraries.
+@end table
+
+@c ============================================================================
+@node postmaster-aliases, postmaster-email, password-file, Configuration Files
+@section postmaster-aliases
+
+@table @strong
+@item Type
+list
+@item Default
+@samp{mailer-daemon}
+@samp{postmaster}
+@samp{root}
+@item Used By
+vsetup
+@item Description
+A list of aliases to the postmaster email address to set
+up when creating a new virtual domain with the vsetup command.
+This should @emph{always} contain both @samp{postmaster} and
+@samp{mailer-daemon} (required by the RFCs), and should usually contain
+@samp{root}.
+@end table
+
+@c ============================================================================
+@node postmaster-email, qmail-root, postmaster-aliases, Configuration Files
+@section postmaster-email
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{postmaster@@}
+@item Used By
+vsetup
+@item Description
+Identifies the email address of the entity responsible
+for the administration of the (virtual) host when building the
+postmaster aliases above.
+If this value ends with a trailing @samp{@@}, the value of
+@file{/var/qmail/control/me} is filled in for the host name.
+If no @samp{@@} is present, the current virtual host name
+is filled in by vdeliver.
+If this is set to @samp{postmaster}, a mail loop
+will result and all mail to this address will bounce.
+@end table
+
+@c ============================================================================
+@node qmail-root, separators, postmaster-email, Configuration Files
+@section qmail-root
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{/var/qmail}
+@item Used By
+checkvpw, vdeliver, vmailmgrd
+@item Description
+Specifies the location of the base directory of your qmail install.
+Set this to whatever you put into @file{conf-home} when you built and
+installed qmail.
+@end table
+
+@c ============================================================================
+@node separators, socket-file, qmail-root, Configuration Files
+@section separators
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{@@:}
+@item Used By
+checkvpw (global only)
+@item Description
+Identifies the set of valid separators within a user login name between
+the virtual user name and virtual domain name when logging in via
+checkvpw.
+For example, if separators contains @samp{@@:} then @samp{user@@domain} and
+@samp{user:domain} are equivalent POP mailbox names.
+@end table
+
+@c ============================================================================
+@node socket-file, user-dir, separators, Configuration Files
+@section socket-file
+
+@table @strong
+@item Type
+string
+@item Default
+@samp{/tmp/.vmailmgrd}
+@item Used By
+vmailmgrd, checkvpw, vdeliver, and the CGI programs
+@item Description
+Identifies the file name of the local socket used to
+communicate between the vmailmgr daemon and the other programs.
+@emph{Warning:} Changing this in the local configuration directories
+will cause vdeliver to fail.
+@end table
+
+@c ============================================================================
+@node user-dir, user-dir-bits, socket-file, Configuration Files
+@section user-dir
+
+@table @strong
+@item Type
+directory
+@item Default
+@samp{users}
+@item Used By
+vmailmgrd and command-line programs
+@item Description
+Identifies the subdirectory from the virtual domain directory in which a
+virtual user's maildir will be created.
+Since this maildir is recorded in the password table, it does not have
+to be the same for each user within a domain.
+This is prefixed with @samp{./} before it is used in the password table.
+@end table
+
+@c ============================================================================
+@node user-dir-bits, user-dir-slices, user-dir, Configuration Files
+@section user-dir-bits
+
+@table @strong
+@item Type
+@item Default
+@samp{0}
+@item Used By
+vmailmgrd and command-line programs when creating new users.
+@item Description
+@xref{user-dir-slices}
+@end table
+
+@c ============================================================================
+@node user-dir-slices, vdeliver-postdeliver, user-dir-bits, Configuration Files
+@section user-dir-slices
+
+@table @strong
+@item Type
+@item Default
+@samp{0}
+@item Used By
+vmailmgrd and command-line programs when creating new users.
+@item Description
+@file{user-dir-bits} and @file{user-dir-slices} work together.  When creating a
+new user directory name, a hash code is generated on the name of the
+new user.  This hash code is split into @file{user-dir-slices} pieces, each
+@file{user-dir-bits} bits long.  Each of these pieces is translated to an
+ASCII string by converting the binary code to hexadecimal.  The
+resulting user directory name is then composed of:
+@itemize @bullet
+@item the base users directory, followed by a @samp{/}
+@item each of the string pieces, each followed by a @samp{/}
+@item the user's name
+@end itemize
+For example, with @file{user-dir-bits} set to 6 and
+@file{user-dir-slices} set to 1, a user
+named @samp{c} maps to a directory name of @samp{users/2f/c/}.
+@end table
+
+@c ============================================================================
+@node vdeliver-postdeliver, vdeliver-predeliver, user-dir-slices, Configuration Files
+@section vdeliver-postdeliver
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+vdeliver
+@item Description
+This list is executed after the delivery is successfully
+completed.
+Since vdeliver expects @samp{USER} and @samp{HOME} to be set, it does
+not set them itself.
+If the command returns with an error code, a warning is printed, but
+delivery does not fail, as failure would lead to duplicates.
+@end table
+
+@c ============================================================================
+@node vdeliver-predeliver, vsetup-post, vdeliver-postdeliver, Configuration Files
+@section vdeliver-predeliver
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+vdeliver
+@item Description
+This list is executed before the delivery is attempted, but
+after the virtual user information is looked up.
+Since vdeliver expects @samp{USER} and @samp{HOME} to be set, it does
+not set them itself.
+@end table
+
+@c ============================================================================
+@node vsetup-post, vsetup-pre, vdeliver-predeliver, Configuration Files
+@section vsetup-pre
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+vsetup
+@item Description
+This list is executed after the vsetup command has sucessfully done
+everything else.
+@end table
+
+
+@c ============================================================================
+@node vsetup-pre,  , vsetup-post, Configuration Files
+@section vsetup-pre
+
+@table @strong
+@item Type
+executable
+@item Default
+Empty
+@item Used By
+vsetup
+@item Description
+This list is executed before the vsetup command makes any changes.
+@end table
+
+
+@contents
+
+@bye
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/configuration.txt	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,626 @@
+
+                         Vmailmgr Configuration Files
+                                       
+14 September 2000
+
+   
+    Bruce Guenter
+     _________________________________________________________________
+   
+                               Table of Contents
+                                       
+     * 1. General Information
+          + 1.1 Search Order
+          + 1.2 File Types
+          + 1.3 Command Execution
+     * 2. Configuration Files
+          + 2.1 authvmailmgr-error
+          + 2.2 authvmailmgr-loginfail
+          + 2.3 authvmailmgr-postsetuid
+          + 2.4 authvmailmgr-presetuid
+          + 2.5 autoresponse-dir
+          + 2.6 autoresponse-file
+          + 2.7 bulletin-dir
+          + 2.8 checkvpw-error
+          + 2.9 checkvpw-loginfail
+          + 2.10 checkvpw-postexec
+          + 2.11 checkvpw-postsetuid
+          + 2.12 checkvpw-presetuid
+          + 2.13 default-expiry
+          + 2.14 default-maildir
+          + 2.15 default-msgcount
+          + 2.16 default-msgsize
+          + 2.17 default-hardquota
+          + 2.18 default-softquota
+          + 2.19 default-username
+          + 2.20 error-maildir
+          + 2.21 global-bulletin-dir
+          + 2.22 maildir-arg-str
+          + 2.23 password-file
+          + 2.24 postmaster-aliases
+          + 2.25 postmaster-email
+          + 2.26 qmail-root
+          + 2.27 separators
+          + 2.28 socket-file
+          + 2.29 user-dir
+          + 2.30 user-dir-bits
+          + 2.31 user-dir-slices
+          + 2.32 vdeliver-postdeliver
+          + 2.33 vdeliver-predeliver
+          + 2.34 vsetup-pre
+          + 2.35 vsetup-pre
+     _________________________________________________________________
+   
+                            1. General Information
+                                       
+1.1 Search Order
+
+   The system will look for the configuration files listed below in one
+   of the following three locations, in the order they are listed:
+    1. The domain-local configuration directory
+    2. The user-local configuration directory
+    3. The global configuration directory
+       
+   The global configuration directory is set to `/etc/vmailmgr' by
+   default. The user-local and domain-local configuration directories
+   (for now, one and the same) are a subdirectory, named `.vmailmgr' by
+   default, of either the user's home directory or the domain
+   subdirectory. If a file matching the configuration name is found in
+   one of the local directories, the search stops and it is not searched
+   for in any higher up directories.
+   
+1.2 File Types
+
+   Each of the configuration files falls into one of the following types:
+   String
+          A single line is read from this type and used as-is with no
+          conversion. All data after the first line is ignored.
+   Directory
+          A single line is read from this type. If it does not have a
+          trailing slash (`/'), one is appended. All data after the first
+          line is ignored.
+   Number
+          A single line is read from this type and converted to an
+          unsigned integer. If the conversion succeeds, the value is
+          used. All data after the first line is ignored.
+   List
+          Each line of the file is read, stripped of leading and trailing
+          whitespace, and treated as a separate value. Lines that contain
+          only whitespace (ie blank lines) or lines beginning with a
+          pound symbol (`#') are ignored.
+   Executable
+          If the execute bits on the file are set, it is treated as an
+          executable file and is executed with no interpretation by
+          vmailmgr. The the Command Execution section below for details.
+          
+   All lines are stripped of any leading or trailing white space.
+   
+   Configuration files marked as `(global only)' are read before any
+   user-level processing occurrs, and so are not functional in the
+   user-level configuration.
+   
+1.3 Command Execution
+
+   The following rules apply to executing a single command or a list of
+   commands.
+   
+   The executables are searched in reverse order of the configuration
+   files. That is, the global setting is used first, and then the local
+   settings. If the named file either does not exist in a directory or is
+   not executable, that directory is skipped.
+   
+   A command exit code of `99' indicates that the command completed
+   successfully but no further commands should be executed. All other
+   non-zero exit codes are treated as an error and will cause the
+   invoking program to stop with the same error code. For `vdeliver', an
+   error exit of 111 will be passed up to qmail as a temporary error, and
+   an error exit of 100 will be passed up as a permanent failure. See the
+   `qmail-command' man page for full details on delivery error codes. For
+   `checkvpw', any non-zero exit code (except as described above) will
+   cause authentication to fail.
+   
+   The following environment variables will be set (where applicable):
+   `HOME'
+          The home directory of the real user.
+   `MAILDIR'
+          The mail directory of the real or virtual user.
+   `USER'
+          The real user's name.
+   `VUSER'
+          The virtual user's name. For base user logins, this is blank,
+          and all the following items prefixed with `VUSER_' are not set.
+   `VUSER_CTIME'
+          The virtual user's creation time (or "0" if unknown).
+   `VUSER_EXPIRY'
+          The virtual user's expiry time (or "-" if not applicable).
+   `VUSER_HARDQUOTA'
+          The virtual user's total size hard quota (in bytes, or "-" if
+          not applicable).
+   `VUSER_MSGCOUNT'
+          The virtual user's message count limit (or "-" if not
+          applicable).
+   `VUSER_MSGSIZE'
+          The virtual user's message size limit (or "-" if not
+          applicable).
+   `VUSER_PERSONAL'
+          The virtual user's personal data.
+   `VUSER_SOFTQUOTA'
+          The virtual user's total size soft quota (in bytes, or "-" if
+          not applicable).
+          
+                            2. Configuration Files
+                                       
+   Each of the following sections identifies a single configuration file
+   
+2.1 authvmailmgr-error
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          authvmailmgr
+   Description
+          This is executed by authvmailmgr if any error occurrs other
+          than those caught by `authvmailmgr-loginfail' below. The
+          environment variable AUTHVMAILMGR_ERROR will contain an error
+          message. This can be used to output logging messages about
+          errors in authvmailmgr.
+          
+2.2 authvmailmgr-loginfail
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          authvmailmgr
+   Description
+          This is executed by authvmailmgr if the user's login fails. The
+          environment variable AUTHVMAILMGR_ERROR will contain an error
+          message. The environment variable VUSER will be set to the
+          virtual user name if it has been determined. This can be used
+          to output logging messages about login failures or to throttle
+          hackers.
+          
+2.3 authvmailmgr-postsetuid
+
+   Type
+          executable
+   Default
+          @samp {vpopbull}
+   Used By
+          authvmailmgr
+   Description
+          This is executed by authvmailmgr after a user is successfully
+          authenticated.
+          
+2.4 authvmailmgr-presetuid
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          authvmailmgr
+   Description
+          This list is executed by authvmailmgr before changing user away
+          from root, and before authenticating a virtual user. Note: The
+          environment variable `MAILDIR' is not set since the virtual
+          user has not yet been authenticated, or even looked up at this
+          point. For the same reason, `VUSER' is not authenticated and is
+          under complete control of the invoking user.
+          
+2.5 autoresponse-dir
+
+   Type
+          directory
+   Default
+          `autoresponse'
+   Used By
+          vmailmgrd, autoresponder script
+   Description
+          Identifies the subdirectory of the virtual user directory in
+          which all autoresponse data is stored.
+          
+2.6 autoresponse-file
+
+   Type
+          string
+   Default
+          `message.txt'
+   Used By
+          vmailmgrd, autoresponder script
+   Description
+          Identifies the file name within the autoresponse directory that
+          contains the autoresponse message.
+          
+2.7 bulletin-dir
+
+   Type
+          directory
+   Default
+          `bulletins'
+   Used By
+          checkvpw
+   Description
+          Identifies the subdirectory of the domain directory in which
+          bulletins local to a domain are stored.
+          
+2.8 checkvpw-error
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          checkvpw
+   Description
+          This is executed by checkvpw if any error occurrs other than
+          those caught by `checkvpw-loginfail' below. The environment
+          variable CHECKVPW_ERROR will contain an error message. This can
+          be used to output logging messages about errors in checkvpw.
+          
+2.9 checkvpw-loginfail
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          checkvpw
+   Description
+          This is executed by checkvpw if the user's login fails. The
+          environment variable CHECKVPW_ERROR will contain an error
+          message. The environment variable VUSER will be set to the
+          virtual user name if it has been determined. This can be used
+          to output logging messages about login failures or to throttle
+          hackers.
+          
+2.10 checkvpw-postexec
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          checkvpw
+   Description
+          This is executed by checkvpw after the subcommand successfully
+          completes.
+          
+2.11 checkvpw-postsetuid
+
+   Type
+          executable
+   Default
+          @samp {vpopbull}
+   Used By
+          checkvpw
+   Description
+          This is executed by checkvpw after a user is successfully
+          authenticated.
+          
+2.12 checkvpw-presetuid
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          checkvpw
+   Description
+          This list is executed by checkvpw before changing user away
+          from root, and before authenticating a virtual user. Note: The
+          environment variable `MAILDIR' is not set since the virtual
+          user has not yet been authenticated, or even looked up at this
+          point. For the same reason, `VUSER' is not authenticated and is
+          under complete control of the invoking user.
+          
+2.13 default-expiry
+
+   Type
+          number
+   Default
+          `-1'
+   Used By
+          vadduser
+   Description
+          Sets the default expiry value for newly created users. Negative
+          values indicate no expiry.
+          
+2.14 default-maildir
+
+   Type
+          directory
+   Default
+          `Maildir'
+   Used By
+          checkvpw
+   Description
+          Sets the name of the directory to be used as a non-virtual
+          user's maildir.
+          
+2.15 default-msgcount
+
+   Type
+          number
+   Default
+          `-1'
+   Used By
+          vadduser
+   Description
+          Sets the default message count limit.
+          
+2.16 default-msgsize
+
+   Type
+          number
+   Default
+          `-1'
+   Used By
+          vadduser
+   Description
+          Sets the default message size limit, in bytes.
+          
+2.17 default-hardquota
+
+   Type
+          number
+   Default
+          `-1'
+   Used By
+          vadduser
+   Description
+          Sets the default hard quota, in bytes.
+          
+2.18 default-softquota
+
+   Type
+          number
+   Default
+          `-1'
+   Used By
+          vadduser
+   Description
+          Sets the default soft quota, in bytes.
+          
+2.19 default-username
+
+   Type
+          string
+   Default
+          `+'
+   Used By
+          vmailmgrd
+   Description
+          Identifies the name of the virtual user to be looked up if a
+          lookup of another virtual user fails.
+          
+2.20 error-maildir
+
+   Type
+          directory
+   Default
+          `/var/lib/vmailmgr/error-maildir'
+   Used By
+          checkvpw
+   Description
+          Specifies the path of a read-only maildir containing a message
+          to be sent to the user when the maildir corresponding to that
+          user does not exist.
+          
+2.21 global-bulletin-dir
+
+   Type
+          directory
+   Default
+          `/var/spool/bulletins'
+   Used By
+          checkvpw
+   Description
+          Identifies a site-wide bulletin directory.
+          
+2.22 maildir-arg-str
+
+   Type
+          string
+   Default
+          `maildir'
+   Used By
+          checkvpw (global only)
+   Description
+          Identifies the string to search for when attempting to identify
+          the maildir argument on the command line to checkvpw.
+          
+2.23 password-file
+
+   Type
+          string
+   Default
+          `passwd'
+   Used By
+          vmailmgrd and command-line programs
+   Description
+          Identifies the file that contains user names, passwords, and
+          destinations for a virtual domain. Note that this has nothing
+          to do with "real" users, for which the password file is
+          determined by the system libraries.
+          
+2.24 postmaster-aliases
+
+   Type
+          list
+   Default
+          `mailer-daemon' `postmaster' `root'
+   Used By
+          vsetup
+   Description
+          A list of aliases to the postmaster email address to set up
+          when creating a new virtual domain with the vsetup command.
+          This should always contain both `postmaster' and
+          `mailer-daemon' (required by the RFCs), and should usually
+          contain `root'.
+          
+2.25 postmaster-email
+
+   Type
+          string
+   Default
+          `postmaster@'
+   Used By
+          vsetup
+   Description
+          Identifies the email address of the entity responsible for the
+          administration of the (virtual) host when building the
+          postmaster aliases above. If this value ends with a trailing
+          `@', the value of `/var/qmail/control/me' is filled in for the
+          host name. If no `@' is present, the current virtual host name
+          is filled in by vdeliver. If this is set to `postmaster', a
+          mail loop will result and all mail to this address will bounce.
+          
+2.26 qmail-root
+
+   Type
+          string
+   Default
+          `/var/qmail'
+   Used By
+          checkvpw, vdeliver, vmailmgrd
+   Description
+          Specifies the location of the base directory of your qmail
+          install. Set this to whatever you put into `conf-home' when you
+          built and installed qmail.
+          
+2.27 separators
+
+   Type
+          string
+   Default
+          `@:'
+   Used By
+          checkvpw (global only)
+   Description
+          Identifies the set of valid separators within a user login name
+          between the virtual user name and virtual domain name when
+          logging in via checkvpw. For example, if separators contains
+          `@:' then `user@domain' and `user:domain' are equivalent POP
+          mailbox names.
+          
+2.28 socket-file
+
+   Type
+          string
+   Default
+          `/tmp/.vmailmgrd'
+   Used By
+          vmailmgrd, checkvpw, vdeliver, and the CGI programs
+   Description
+          Identifies the file name of the local socket used to
+          communicate between the vmailmgr daemon and the other programs.
+          Warning: Changing this in the local configuration directories
+          will cause vdeliver to fail.
+          
+2.29 user-dir
+
+   Type
+          directory
+   Default
+          `users'
+   Used By
+          vmailmgrd and command-line programs
+   Description
+          Identifies the subdirectory from the virtual domain directory
+          in which a virtual user's maildir will be created. Since this
+          maildir is recorded in the password table, it does not have to
+          be the same for each user within a domain. This is prefixed
+          with `./' before it is used in the password table.
+          
+2.30 user-dir-bits
+
+   Type
+   Default
+          `0'
+   Used By
+          vmailmgrd and command-line programs when creating new users.
+   Description
+          See section 2.31 user-dir-slices
+          
+2.31 user-dir-slices
+
+   Type
+   Default
+          `0'
+   Used By
+          vmailmgrd and command-line programs when creating new users.
+   Description
+          `user-dir-bits' and `user-dir-slices' work together. When
+          creating a new user directory name, a hash code is generated on
+          the name of the new user. This hash code is split into
+          `user-dir-slices' pieces, each `user-dir-bits' bits long. Each
+          of these pieces is translated to an ASCII string by converting
+          the binary code to hexadecimal. The resulting user directory
+          name is then composed of:
+          + the base users directory, followed by a `/'
+          + each of the string pieces, each followed by a `/'
+          + the user's name
+          For example, with `user-dir-bits' set to 6 and
+          `user-dir-slices' set to 1, a user named `c' maps to a
+          directory name of `users/2f/c/'.
+          
+2.32 vdeliver-postdeliver
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          vdeliver
+   Description
+          This list is executed after the delivery is successfully
+          completed. Since vdeliver expects `USER' and `HOME' to be set,
+          it does not set them itself. If the command returns with an
+          error code, a warning is printed, but delivery does not fail,
+          as failure would lead to duplicates.
+          
+2.33 vdeliver-predeliver
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          vdeliver
+   Description
+          This list is executed before the delivery is attempted, but
+          after the virtual user information is looked up. Since vdeliver
+          expects `USER' and `HOME' to be set, it does not set them
+          itself.
+          
+2.34 vsetup-pre
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          vsetup
+   Description
+          This list is executed after the vsetup command has sucessfully
+          done everything else.
+          
+2.35 vsetup-pre
+
+   Type
+          executable
+   Default
+          Empty
+   Used By
+          vsetup
+   Description
+          This list is executed before the vsetup command makes any
+          changes.
+     _________________________________________________________________
+   
+   This document was generated on 14 September 2000 using
+   texi2html 1.56k.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/news2html.pl	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+print <<HEAD;
+<html>
+<head>
+<title>Release History</title>
+<body>
+<center><h1>Release History</h1></center>
+HEAD
+
+$ul = 0;
+
+while(<>) {
+    chomp;
+    if(/^\s*$/) {
+	print "<p>";
+    } elsif(/^----------------------------------/) {
+	print "</ul>\n" if $ul; $ul = 0;
+	print "<hr>";
+    } elsif(/^Changes in version/i) {
+	print "<h2>", $_, "</h2>";
+    } elsif(/^-/ || /^\s/) {
+	print "<ul>\n" unless $ul; $ul = 1;
+	s/^- /<li>/;
+	print;
+    } else {
+	print "</ul>\n" if $ul; $ul = 0;
+	print;
+    }
+    print "\n";
+}
+
+print <<TAIL;
+</body>
+</html>
+TAIL
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/protocol.txt	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,43 @@
+Client-Server interaction
+-------------------------
+
+To execute a server call, the client opens the daemon's UNIX domain
+socket (as specified by SYSCONFDIR/socket-file), and sends across the
+following data:
+
+Size	Type	Description
+1	int	Protocol number (always 2)
+2	int	Total length of all data
+1	int	Number of arguments following the command
+varies	string	Command name
+varies	strings	Arguments
+
+It then receives the following response from the server:
+
+Size	Type	Description
+1	int	Response code: one of the following
+		0: OK -- operation succeeded
+		1: Bad -- error in format or syntax
+		2: Error -- operation failed
+varies	string	Message
+
+
+Strings are encoded as:
+
+Size	Type	Description
+2	int	Length of string
+length	char	String data (no trailing NUL byte)
+
+All integers are unsigned, sent MSB first.
+
+Example:
+0x02                   Protocol version
+0x00 0x2E              Length of everything from this point on
+0x02                   Number of arguments to command
+0x00 0x0A              Length of command name (command name will become a
+                       number later)
+listdomain             Command name
+0x00 0x15              Length of first argument
+mailtest.somesuch.dom  First argument
+0x00 0x08              Length of second argument
+mailtest               Second argument
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/record-format.txt	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,74 @@
+Record Format
+-------------
+
+Syntax notes:
+- ( P )* means "zero or more of the P"
+- ( P )+ means "one or more of the P"
+- { P } means "zero or one of the P"
+  (ie P is optional and may be omitted)
+
+New version 2 records have the following format:
+	0x02
+	( flag-number flag-value )* NUL
+	password-crypt NUL
+	{ mailbox } NUL
+	( alias NUL )* NUL
+	personal-information NUL
+	hard-quota NUL
+	soft-quota NUL
+	message-size-limit NUL
+	message-count-limit NUL
+	creation-time NUL
+	expiry-time NUL
+
+flag-number and flag-value are single-byte values.  The flag numbers are
+the same as the attribute number defined in vdomain/vdomain.h.
+
+The maximum values for limits (quota, etc.) are expressed in the file as
+"-" and internally as UINT_MAX.  Records with an unknown creation time
+have the creation-time set to the UNIX epoch (midnight GMT January 1,
+1970).
+
+Old Record Formats
+------------------
+
+Version 1 records have the following format:
+	0x01
+	password-crypt NUL
+	{ mailbox } NUL
+	( alias NUL )* NUL
+	personal-information NUL
+	hard-quota NUL
+	soft-quota NUL
+	message-size-limit NUL
+	message-count-limit NUL
+	creation-time NUL
+	expiry-time NUL
+
+Old style records had the following format:
+	":" password-crypt ":" destination
+The destination was prefixed with '&' for a forward, and with either '.'
+or '/' for a mailbox.
+
+Proposed Record Format
+----------------------
+
+New version 3 records have the following format:
+	0x03
+	( flag-number flag-value )* NUL
+	password-crypt NUL
+	{ mailbox } NUL
+	( alias NUL )* NUL
+	personal-information NUL
+	hard-quota NUL
+	soft-quota NUL
+	message-size-limit NUL
+	message-count-limit NUL
+	creation-time NUL
+	expiry-time NUL
+	last-modified-time NUL
+
+flag-number and flag-value are single-byte values.  The flag numbers are
+the same as the attribute number defined in vdomain/vdomain.h.  The flag
+value is either ASCII '0' for false/off or ASCII '1' for true/on.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/translation.fig	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,162 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+6 750 525 1650 825
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 750 525 1650 525 1650 825 750 825 750 525
+4 1 0 0 0 4 12 0.0000 4 90 780 1200 750 username\001
+-6
+6 1950 525 2850 825
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 1950 525 2850 525 2850 825 1950 825 1950 525
+4 1 0 0 0 4 12 0.0000 4 135 765 2400 750 hostname\001
+-6
+6 1050 1500 2550 1800
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 1050 1500 2550 1500 2550 1800 1050 1800 1050 1500
+4 1 0 0 0 4 12 0.0000 4 180 1395 1800 1725 prefix-username\001
+-6
+6 825 2325 1575 2625
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 825 2325 1575 2325 1575 2625 825 2625 825 2325
+4 1 0 0 0 4 12 0.0000 4 150 660 1200 2550 pwentry\001
+-6
+6 1875 2325 2925 2625
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2925 2625 1875 2625 1875 2325 2925 2325 2925 2625
+4 1 0 0 0 4 12 0.0000 4 135 945 2400 2550 virtualname\001
+-6
+6 1950 3225 2850 3525
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2850 3525 1950 3525 1950 3225 2850 3225 2850 3525
+4 1 0 0 0 4 12 0.0000 4 150 750 2400 3450 vpwentry\001
+-6
+6 1875 4125 2925 4425
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2925 4425 1875 4425 1875 4125 2925 4125 2925 4425
+4 1 0 0 0 4 12 0.0000 4 135 870 2400 4350 destination\001
+-6
+6 2850 2775 4200 3075
+2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5
+	 2850 2775 2850 3075 4200 3075 4200 2775 2850 2775
+4 1 0 0 0 4 12 0.0000 4 180 1140 3525 3000 virtual passwd\001
+-6
+6 6600 3225 7650 3525
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 7650 3525 6600 3525 6600 3225 7650 3225 7650 3525
+4 1 0 0 0 4 12 0.0000 4 135 945 7125 3450 virtualname\001
+-6
+6 5625 3225 6525 3525
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 6525 3525 5625 3525 5625 3225 6525 3225 6525 3525
+4 1 0 0 0 4 12 0.0000 4 135 675 6075 3450 vdomain\001
+-6
+6 6150 4125 7050 4425
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 7050 4425 6150 4425 6150 4125 7050 4125 7050 4425
+4 1 0 0 0 4 12 0.0000 4 150 750 6600 4350 vpwentry\001
+-6
+6 6075 5100 7125 5400
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 7125 5400 6075 5400 6075 5100 7125 5100 7125 5400
+4 1 0 0 0 4 12 0.0000 4 135 870 6600 5325 destination\001
+-6
+6 6150 2325 7200 2625
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 6150 2325 7200 2325 7200 2625 6150 2625 6150 2325
+4 1 0 0 0 4 12 0.0000 4 135 945 6675 2550 virtualname\001
+-6
+6 5100 2325 5850 2625
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 5100 2325 5850 2325 5850 2625 5100 2625 5100 2325
+4 1 0 0 0 4 12 0.0000 4 150 660 5475 2550 pwentry\001
+-6
+6 5100 1800 8400 2250
+4 1 0 0 0 6 16 0.0000 4 195 2760 6750 1950 Future translation plan\001
+4 1 0 0 0 6 16 0.0000 4 210 3240 6750 2175 (multiple domains per user)\001
+-6
+6 1050 5100 1800 5400
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 1800 5400 1050 5400 1050 5100 1800 5100 1800 5400
+4 1 0 0 0 4 12 0.0000 4 180 495 1425 5325 Object\001
+-6
+6 1050 5550 1800 5850
+2 4 0 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 1050 5550 1050 5850 1800 5850 1800 5550 1050 5550
+4 1 0 0 0 4 12 0.0000 4 180 495 1425 5775 Object\001
+-6
+6 7425 2775 8925 3075
+2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5
+	 7425 2775 7425 3075 8925 3075 8925 2775 7425 2775
+4 1 0 0 0 4 12 0.0000 4 180 1185 8175 3000 vdomain config\001
+-6
+6 2850 1050 4200 1350
+2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5
+	 4200 1350 4200 1050 2850 1050 2850 1350 4200 1350
+4 1 0 0 0 4 12 0.0000 4 135 1170 3525 1275 virtualdomains\001
+-6
+6 3450 1950 4200 2250
+2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5
+	 4200 2250 4200 1950 3450 1950 3450 2250 4200 2250
+4 1 0 0 0 4 12 0.0000 4 180 585 3825 2175 passwd\001
+-6
+6 7575 3675 8925 3975
+2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5
+	 7575 3675 7575 3975 8925 3975 8925 3675 7575 3675
+4 1 0 0 0 4 12 0.0000 4 180 1140 8250 3900 virtual passwd\001
+-6
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 1200 825 1725 1500
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 2400 825 1875 1500
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 1725 1800 1200 2325
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 1875 1800 2400 2325
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 2400 2625 2400 3225
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 2400 3525 2400 4125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 5475 2625 6000 3225
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 7125 3525 6675 4125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 6075 3525 6525 4125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 6600 4425 6600 5100
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 6675 2625 7125 3225
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 6675 2625 6150 3225
+2 1 5 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 3075 2475 4950 2475
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 1125 6075 1725 6075
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 2
+	 1050 5025 4950 5025
+4 1 0 0 0 6 16 0.0000 4 195 6120 3750 300 Description of mailbox name translation in VMailMgr\001
+4 0 0 0 0 4 12 0.0000 4 180 630 1050 4950 Legend:\001
+4 0 0 0 0 4 12 0.0000 4 165 2040 1950 5775 External construct (ie file)\001
+4 0 0 0 0 4 12 0.0000 4 165 1200 1950 6150 Processing step\001
+4 0 0 0 0 4 12 0.0000 4 165 2835 1950 5325 Internal construct (ie struct or class)\001
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/translation.ps	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,428 @@
+%!PS-Adobe-2.0
+%%Title: translation.fig
+%%Creator: fig2dev Version 3.2.3 Patchlevel 
+%%CreationDate: Sat Sep 30 22:24:36 2000
+%%For: bruce@bruce-guenter.dyndns.org (Bruce Guenter)
+%%Orientation: Landscape
+%%Pages: 1
+%%BoundingBox: 0 0 612 792
+%%BeginSetup
+%%IncludeFeature: *PageSize Letter
+%%EndSetup
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 792 moveto 0 0 lineto 612 0 lineto 612 792 lineto closepath clip newpath
+116.0 109.5 translate
+ 90 rotate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+  bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+  4 -2 roll mul srgb} bind def
+/reencdict 12 dict def /ReEncode { reencdict begin
+/newcodesandnames exch def /newfontname exch def /basefontname exch def
+/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
+basefontdict { exch dup /FID ne { dup /Encoding eq
+{ exch dup length array copy newfont 3 1 roll put }
+{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
+newfont /FontName newfontname put newcodesandnames aload pop
+128 1 255 { newfont /Encoding get exch /.notdef put } for
+newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
+newfontname newfont definefont pop end } def
+/isovec [
+8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
+8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
+8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
+8#220 /dotlessi 8#230 /oe 8#231 /OE
+8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
+8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
+8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
+8#255 /hypen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
+8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
+8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
+8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
+8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
+8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
+8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
+8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
+8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
+8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
+8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
+8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
+8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
+8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
+8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
+8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
+8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
+8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
+8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def
+/AvantGarde-Demi /AvantGarde-Demi-iso isovec ReEncode
+/AvantGarde-Book /AvantGarde-Book-iso isovec ReEncode
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+%%Page: 1 1
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%%Page: 1 1
+% Polyline
+7.500 slw
+n 750 525 m 1650 525 l 1650 825 l 750 825 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+1200 750 m
+gs 1 -1 sc (username) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 1950 525 m 2850 525 l 2850 825 l 1950 825 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+2400 750 m
+gs 1 -1 sc (hostname) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 1050 1500 m 2550 1500 l 2550 1800 l 1050 1800 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+1800 1725 m
+gs 1 -1 sc (prefix-username) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 825 2325 m 1575 2325 l 1575 2625 l 825 2625 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+1200 2550 m
+gs 1 -1 sc (pwentry) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 2925 2625 m 1875 2625 l 1875 2325 l 2925 2325 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+2400 2550 m
+gs 1 -1 sc (virtualname) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 2850 3525 m 1950 3525 l 1950 3225 l 2850 3225 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+2400 3450 m
+gs 1 -1 sc (vpwentry) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 2925 4425 m 1875 4425 l 1875 4125 l 2925 4125 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+2400 4350 m
+gs 1 -1 sc (destination) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 2955 2775 m 2850 2775 2850 2970 105 arcto 4 {pop} repeat
+  2850 3075 4095 3075 105 arcto 4 {pop} repeat
+  4200 3075 4200 2880 105 arcto 4 {pop} repeat
+  4200 2775 2955 2775 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+3525 3000 m
+gs 1 -1 sc (virtual passwd) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 7650 3525 m 6600 3525 l 6600 3225 l 7650 3225 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+7125 3450 m
+gs 1 -1 sc (virtualname) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 6525 3525 m 5625 3525 l 5625 3225 l 6525 3225 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+6075 3450 m
+gs 1 -1 sc (vdomain) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 7050 4425 m 6150 4425 l 6150 4125 l 7050 4125 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+6600 4350 m
+gs 1 -1 sc (vpwentry) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 7125 5400 m 6075 5400 l 6075 5100 l 7125 5100 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+6600 5325 m
+gs 1 -1 sc (destination) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 6150 2325 m 7200 2325 l 7200 2625 l 6150 2625 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+6675 2550 m
+gs 1 -1 sc (virtualname) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 5100 2325 m 5850 2325 l 5850 2625 l 5100 2625 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+5475 2550 m
+gs 1 -1 sc (pwentry) dup sw pop 2 div neg 0 rm  col0 sh gr
+/AvantGarde-Demi-iso ff 240.00 scf sf
+6750 1950 m
+gs 1 -1 sc (Future translation plan) dup sw pop 2 div neg 0 rm  col0 sh gr
+/AvantGarde-Demi-iso ff 240.00 scf sf
+6750 2175 m
+gs 1 -1 sc (\(multiple domains per user\)) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 1800 5400 m 1050 5400 l 1050 5100 l 1800 5100 l
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+1425 5325 m
+gs 1 -1 sc (Object) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 1155 5550 m 1050 5550 1050 5745 105 arcto 4 {pop} repeat
+  1050 5850 1695 5850 105 arcto 4 {pop} repeat
+  1800 5850 1800 5655 105 arcto 4 {pop} repeat
+  1800 5550 1155 5550 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+1425 5775 m
+gs 1 -1 sc (Object) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 7530 2775 m 7425 2775 7425 2970 105 arcto 4 {pop} repeat
+  7425 3075 8820 3075 105 arcto 4 {pop} repeat
+  8925 3075 8925 2880 105 arcto 4 {pop} repeat
+  8925 2775 7530 2775 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+8175 3000 m
+gs 1 -1 sc (vdomain config) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 2955 1050 m 2850 1050 2850 1245 105 arcto 4 {pop} repeat
+  2850 1350 4095 1350 105 arcto 4 {pop} repeat
+  4200 1350 4200 1155 105 arcto 4 {pop} repeat
+  4200 1050 2955 1050 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+3525 1275 m
+gs 1 -1 sc (virtualdomains) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 3555 1950 m 3450 1950 3450 2145 105 arcto 4 {pop} repeat
+  3450 2250 4095 2250 105 arcto 4 {pop} repeat
+  4200 2250 4200 2055 105 arcto 4 {pop} repeat
+  4200 1950 3555 1950 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+3825 2175 m
+gs 1 -1 sc (passwd) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+n 7680 3675 m 7575 3675 7575 3870 105 arcto 4 {pop} repeat
+  7575 3975 8820 3975 105 arcto 4 {pop} repeat
+  8925 3975 8925 3780 105 arcto 4 {pop} repeat
+  8925 3675 7680 3675 105 arcto 4 {pop} repeat
+ cp gs col0 s gr 
+/AvantGarde-Book-iso ff 180.00 scf sf
+8250 3900 m
+gs 1 -1 sc (virtual passwd) dup sw pop 2 div neg 0 rm  col0 sh gr
+% Polyline
+gs  clippath
+1710 1530 m 1757 1493 l 1665 1373 l 1715 1487 l 1617 1410 l cp
+eoclip
+n 1200 825 m
+ 1725 1500 l gs col0 s gr gr
+
+% arrowhead
+n 1617 1410 m 1715 1487 l 1665 1373 l 1617 1410 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+1842 1493 m 1889 1530 l 1982 1410 l 1885 1487 l 1934 1373 l cp
+eoclip
+n 2400 825 m
+ 1875 1500 l gs col0 s gr gr
+
+% arrowhead
+n 1934 1373 m 1885 1487 l 1982 1410 l 1934 1373 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+1168 2314 m 1210 2356 l 1317 2250 l 1211 2314 l 1274 2207 l cp
+eoclip
+n 1725 1800 m
+ 1200 2325 l gs col0 s gr gr
+
+% arrowhead
+n 1274 2207 m 1211 2314 l 1317 2250 l 1274 2207 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+2389 2356 m 2431 2314 l 2325 2207 l 2389 2314 l 2282 2250 l cp
+eoclip
+n 1875 1800 m
+ 2400 2325 l gs col0 s gr gr
+
+% arrowhead
+n 2282 2250 m 2389 2314 l 2325 2207 l 2282 2250 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+2370 3240 m 2430 3240 l 2430 3089 l 2400 3209 l 2370 3089 l cp
+eoclip
+n 2400 2625 m
+ 2400 3225 l gs col0 s gr gr
+
+% arrowhead
+n 2370 3089 m 2400 3209 l 2430 3089 l 2370 3089 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+2370 4140 m 2430 4140 l 2430 3989 l 2400 4109 l 2370 3989 l cp
+eoclip
+n 2400 3525 m
+ 2400 4125 l gs col0 s gr gr
+
+% arrowhead
+n 2370 3989 m 2400 4109 l 2430 3989 l 2370 3989 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+5987 3256 m 6032 3216 l 5932 3102 l 5989 3213 l 5887 3142 l cp
+eoclip
+n 5475 2625 m
+ 6000 3225 l gs col0 s gr gr
+
+% arrowhead
+n 5887 3142 m 5989 3213 l 5932 3102 l 5887 3142 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+6642 4119 m 6690 4154 l 6780 4033 l 6685 4112 l 6732 3998 l cp
+eoclip
+n 7125 3525 m
+ 6675 4125 l gs col0 s gr gr
+
+% arrowhead
+n 6732 3998 m 6685 4112 l 6780 4033 l 6732 3998 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+6509 4154 m 6557 4119 l 6467 3998 l 6515 4112 l 6419 4033 l cp
+eoclip
+n 6075 3525 m
+ 6525 4125 l gs col0 s gr gr
+
+% arrowhead
+n 6419 4033 m 6515 4112 l 6467 3998 l 6419 4033 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+6570 5115 m 6630 5115 l 6630 4964 l 6600 5084 l 6570 4964 l cp
+eoclip
+n 6600 4425 m
+ 6600 5100 l gs col0 s gr gr
+
+% arrowhead
+n 6570 4964 m 6600 5084 l 6630 4964 l 6570 4964 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+7109 3254 m 7157 3219 l 7067 3098 l 7115 3212 l 7019 3133 l cp
+eoclip
+n 6675 2625 m
+ 7125 3225 l gs col0 s gr gr
+
+% arrowhead
+n 7019 3133 m 7115 3212 l 7067 3098 l 7019 3133 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+6117 3216 m 6162 3256 l 6262 3142 l 6161 3213 l 6217 3102 l cp
+eoclip
+n 6675 2625 m
+ 6150 3225 l gs col0 s gr gr
+
+% arrowhead
+n 6217 3102 m 6161 3213 l 6262 3142 l 6217 3102 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+ [60 24 15 18 15 18 15 24 ] 0 sd
+gs  clippath
+4965 2505 m 4965 2445 l 4814 2445 l 4934 2475 l 4814 2505 l cp
+eoclip
+n 3075 2475 m
+ 4950 2475 l gs col0 s gr gr
+ [] 0 sd
+% arrowhead
+n 4814 2505 m 4934 2475 l 4814 2445 l 4814 2505 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+gs  clippath
+1740 6105 m 1740 6045 l 1589 6045 l 1709 6075 l 1589 6105 l cp
+eoclip
+n 1125 6075 m
+ 1725 6075 l gs col0 s gr gr
+
+% arrowhead
+n 1589 6105 m 1709 6075 l 1589 6045 l 1589 6105 l  cp gs 0.00 setgray ef gr  col0 s
+% Polyline
+n 1050 5025 m
+ 4950 5025 l gs col0 s gr 
+/AvantGarde-Demi-iso ff 240.00 scf sf
+3750 300 m
+gs 1 -1 sc (Description of mailbox name translation in VMailMgr) dup sw pop 2 div neg 0 rm  col0 sh gr
+/AvantGarde-Book-iso ff 180.00 scf sf
+1050 4950 m
+gs 1 -1 sc (Legend:) col0 sh gr
+/AvantGarde-Book-iso ff 180.00 scf sf
+1950 5775 m
+gs 1 -1 sc (External construct \(ie file\)) col0 sh gr
+/AvantGarde-Book-iso ff 180.00 scf sf
+1950 6150 m
+gs 1 -1 sc (Processing step) col0 sh gr
+/AvantGarde-Book-iso ff 180.00 scf sf
+1950 5325 m
+gs 1 -1 sc (Internal construct \(ie struct or class\)) col0 sh gr
+$F2psEnd
+rs
+showpage
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/vmailmgr-cgi.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,748 @@
+<HTML>
+<HEAD>
+<!-- Created by texi2html 1.56k from vmailmgr-cgi.texi on 14 September 2000 -->
+
+<TITLE>vmailmgr CGI Documentation</TITLE>
+</HEAD>
+<BODY>
+<H1>vmailmgr CGI Documentation</H1>
+<H2>14 September 2000</H2>
+<ADDRESS>Bruce Guenter</ADDRESS>
+<P>
+<P><HR><P>
+<H1>Table of Contents</H1>
+<UL>
+<LI><A NAME="TOC1" HREF="vmailmgr-cgi.html#SEC1">1. Introduction</A>
+<UL>
+<LI><A NAME="TOC2" HREF="vmailmgr-cgi.html#SEC2">1.1 Common Form Configuration</A>
+<UL>
+<LI><A NAME="TOC3" HREF="vmailmgr-cgi.html#SEC3">1.1.1 Required Form Fields</A>
+<LI><A NAME="TOC4" HREF="vmailmgr-cgi.html#SEC4">1.1.2 Optional Form Fields</A>
+</UL>
+</UL>
+<LI><A NAME="TOC5" HREF="vmailmgr-cgi.html#SEC5">2. listvdomain</A>
+<UL>
+<LI><A NAME="TOC6" HREF="vmailmgr-cgi.html#SEC6">2.1 Overview</A>
+<LI><A NAME="TOC7" HREF="vmailmgr-cgi.html#SEC7">2.2 Form Configuration</A>
+<UL>
+<LI><A NAME="TOC8" HREF="vmailmgr-cgi.html#SEC8">2.2.1 Required Form Fields</A>
+<LI><A NAME="TOC9" HREF="vmailmgr-cgi.html#SEC9">2.2.2 Optional Form Fields</A>
+</UL>
+</UL>
+<LI><A NAME="TOC10" HREF="vmailmgr-cgi.html#SEC10">3. vaddalias</A>
+<UL>
+<LI><A NAME="TOC11" HREF="vmailmgr-cgi.html#SEC11">3.1 Overview</A>
+<LI><A NAME="TOC12" HREF="vmailmgr-cgi.html#SEC12">3.2 Form Configuration</A>
+<UL>
+<LI><A NAME="TOC13" HREF="vmailmgr-cgi.html#SEC13">3.2.1 Required Form Fields</A>
+<LI><A NAME="TOC14" HREF="vmailmgr-cgi.html#SEC14">3.2.2 Optional Form Fields</A>
+</UL>
+</UL>
+<LI><A NAME="TOC15" HREF="vmailmgr-cgi.html#SEC15">4. vadduser</A>
+<UL>
+<LI><A NAME="TOC16" HREF="vmailmgr-cgi.html#SEC16">4.1 Overview</A>
+<LI><A NAME="TOC17" HREF="vmailmgr-cgi.html#SEC17">4.2 Form Configuration</A>
+<UL>
+<LI><A NAME="TOC18" HREF="vmailmgr-cgi.html#SEC18">4.2.1 Required Form Fields</A>
+<LI><A NAME="TOC19" HREF="vmailmgr-cgi.html#SEC19">4.2.2 Optional Form Fields</A>
+</UL>
+</UL>
+<LI><A NAME="TOC20" HREF="vmailmgr-cgi.html#SEC20">5. vchattr</A>
+<UL>
+<LI><A NAME="TOC21" HREF="vmailmgr-cgi.html#SEC21">5.1 Overview</A>
+<LI><A NAME="TOC22" HREF="vmailmgr-cgi.html#SEC22">5.2 Form Configuration</A>
+<UL>
+<LI><A NAME="TOC23" HREF="vmailmgr-cgi.html#SEC23">5.2.1 Required Form Fields</A>
+</UL>
+</UL>
+<LI><A NAME="TOC24" HREF="vmailmgr-cgi.html#SEC24">6. vchforwards</A>
+<UL>
+<LI><A NAME="TOC25" HREF="vmailmgr-cgi.html#SEC25">6.1 Overview</A>
+<LI><A NAME="TOC26" HREF="vmailmgr-cgi.html#SEC26">6.2 Form Configuration</A>
+<UL>
+<LI><A NAME="TOC27" HREF="vmailmgr-cgi.html#SEC27">6.2.1 Required Form Fields</A>
+<LI><A NAME="TOC28" HREF="vmailmgr-cgi.html#SEC28">6.2.2 Optional Form Fields</A>
+</UL>
+</UL>
+<LI><A NAME="TOC29" HREF="vmailmgr-cgi.html#SEC29">7. vdeluser</A>
+<UL>
+<LI><A NAME="TOC30" HREF="vmailmgr-cgi.html#SEC30">7.1 Overview</A>
+<LI><A NAME="TOC31" HREF="vmailmgr-cgi.html#SEC31">7.2 Form Configuration</A>
+<UL>
+<LI><A NAME="TOC32" HREF="vmailmgr-cgi.html#SEC32">7.2.1 Required Form Fields</A>
+</UL>
+</UL>
+<LI><A NAME="TOC33" HREF="vmailmgr-cgi.html#SEC33">8. vpasswd</A>
+<UL>
+<LI><A NAME="TOC34" HREF="vmailmgr-cgi.html#SEC34">8.1 Overview</A>
+<LI><A NAME="TOC35" HREF="vmailmgr-cgi.html#SEC35">8.2 Form Configuration</A>
+<UL>
+<LI><A NAME="TOC36" HREF="vmailmgr-cgi.html#SEC36">8.2.1 Required Form Fields</A>
+</UL>
+</UL>
+</UL>
+<P><HR><P>
+
+
+<H1><A NAME="SEC1" HREF="vmailmgr-cgi.html#TOC1">1. Introduction</A></H1>
+
+<P>
+This is the documentation for the CGI programs for vmailmgr.
+
+
+
+
+<H2><A NAME="SEC2" HREF="vmailmgr-cgi.html#TOC2">1.1 Common Form Configuration</A></H2>
+
+<P>
+The following form fields are common to all of the vmailmgr CGI
+programs.
+
+
+
+
+<H3><A NAME="SEC3" HREF="vmailmgr-cgi.html#TOC3">1.1.1 Required Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        vdomain
+<DT><STRONG>Description:</STRONG>
+<DD>
+This field specifies the name of the virtual domain under which to
+perform this operation.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=vdomain value="<VAR>domain-name</VAR>"&#62;'</SAMP>
+or
+<SAMP>`&#60;input type=text name=vdomain&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        password
+<DT><STRONG>Description:</STRONG>
+<DD>
+Unless noted below, this field specifies the password of the
+administrator for the given virtual domain.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=password name=password&#62;'</SAMP>
+</DL>
+
+
+
+<H3><A NAME="SEC4" HREF="vmailmgr-cgi.html#TOC4">1.1.2 Optional Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        error_redirect
+<DT><STRONG>Description:</STRONG>
+<DD>
+If this field is set, any operation that results in an error will be
+redirected to the given URL.
+If not set, a pre-programmed document (which includes the error message)
+will be output.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=error_redirect value="<VAR>URL</VAR>"&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        redirect
+<DT><STRONG>Description:</STRONG>
+<DD>
+If this field is set, any operation that completes successfully with be
+redirected to the given URL.
+If not set, a pre-programmed document (which includes the completion
+message) will be output.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=redirect value="<VAR>URL</VAR>"&#62;'</SAMP>
+</DL>
+
+
+
+<H1><A NAME="SEC5" HREF="vmailmgr-cgi.html#TOC5">2. listvdomain</A></H1>
+
+
+
+<H2><A NAME="SEC6" HREF="vmailmgr-cgi.html#TOC6">2.1 Overview</A></H2>
+
+<P>
+This CGI program will list the mailboxes and aliases in a virtual domain
+in a three-column table.
+The first column lists the mailbox or alias name,
+the second column is either <SAMP>`Alias'</SAMP> or <SAMP>`Mailbox'</SAMP>,
+and the third column lists the destination.
+
+
+
+
+<H2><A NAME="SEC7" HREF="vmailmgr-cgi.html#TOC7">2.2 Form Configuration</A></H2>
+
+
+
+<H3><A NAME="SEC8" HREF="vmailmgr-cgi.html#TOC8">2.2.1 Required Form Fields</A></H3>
+
+<P>
+No additional form fields are Required.
+
+
+
+
+<H3><A NAME="SEC9" HREF="vmailmgr-cgi.html#TOC9">2.2.2 Optional Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        body-flags
+<DT><STRONG>Description:</STRONG>
+<DD>
+If present, the contents of this field is inserted into the
+<SAMP>`&#60;body&#62;'</SAMP> tag at the start of the document.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=body-flags value="bgcolor=ffffff"&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        cell-align
+<DT><STRONG>Description:</STRONG>
+<DD>
+Sets the cell alignment.
+Defaults to <SAMP>`left'</SAMP>.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=cell-align value=center&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        cell-post
+<DT><STRONG>Description:</STRONG>
+<DD>
+If present, the contents of this field will be output prior to every
+<SAMP>`&#60;/td&#62;'</SAMP> tag.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=cell-post value="&#60;/font&#62;"&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        cell-pre
+<DT><STRONG>Description:</STRONG>
+<DD>
+If present, the contents of this field will be output after every
+<SAMP>`&#60;td&#62;'</SAMP> tag.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=cell-pre value="&#60;font size=1 name=ariel&#62;"&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        p-align
+<DT><STRONG>Description:</STRONG>
+<DD>
+Sets the default paragraph alignment.
+Defaults to <SAMP>`left'</SAMP>.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=p-align value=center&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        title-post
+<DT><STRONG>Description:</STRONG>
+<DD>
+If present, the contents of this field are output after the title text.
+Defaults to <SAMP>`&#60;/h1&#62;'</SAMP>.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=title-post value="&#60;/font&#62;"&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        table-align
+<DT><STRONG>Description:</STRONG>
+<DD>
+Sets the allignment of the table listing the users.
+Defaults to <SAMP>`left'</SAMP>.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=table-align value=center&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        title-pre
+<DT><STRONG>Description:</STRONG>
+<DD>
+If present, the contents of this field are output before the title text.
+Defaults to <SAMP>`&#60;h1&#62;'</SAMP>.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=title-pre value="&#60;font size=3 face=verdana&#62;"&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        userlink
+<DT><STRONG>Description:</STRONG>
+<DD>
+If this field is present, all user names will be enclosed in a link to the
+contents of this field.  If the field contains a '%', it will be
+replaced by the user name.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=userlink value="/cgi-bin/admin-user?name=%"&#62;'</SAMP>
+</DL>
+
+
+
+<H1><A NAME="SEC10" HREF="vmailmgr-cgi.html#TOC10">3. vaddalias</A></H1>
+
+
+
+<H2><A NAME="SEC11" HREF="vmailmgr-cgi.html#TOC11">3.1 Overview</A></H2>
+
+<P>
+This CGI program can be used to add an alias to a virtual domain.
+
+
+
+
+<H2><A NAME="SEC12" HREF="vmailmgr-cgi.html#TOC12">3.2 Form Configuration</A></H2>
+
+
+
+<H3><A NAME="SEC13" HREF="vmailmgr-cgi.html#TOC13">3.2.1 Required Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        username
+<DT><STRONG>Description:</STRONG>
+<DD>
+The virtual user name of the alias to create.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=username&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        destination
+<DT><STRONG>Description:</STRONG>
+<DD>
+The destination address or addresses of the alias, separated by commas.
+If an address does not contain a host name (separated from the user name
+with an <SAMP>`@'</SAMP>), it is treated as local to the virtual domain and
+must already exist.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=destination&#62;'</SAMP>
+</DL>
+
+
+
+<H3><A NAME="SEC14" HREF="vmailmgr-cgi.html#TOC14">3.2.2 Optional Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        newpass1, newpass2
+<DT><STRONG>Description:</STRONG>
+<DD>
+These two fields specify the new password of the user. They must match
+for the password to be changed. The first eight characters are relevant,
+and may be any combination of letters, digits, or punctuation symbols.
+If these fields are not present or are empty, a null passcode is used.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=password name=newpass1&#62;&#60;input type=password name=newpass1&#62;'</SAMP>
+</DL>
+
+
+
+<H1><A NAME="SEC15" HREF="vmailmgr-cgi.html#TOC15">4. vadduser</A></H1>
+
+
+
+<H2><A NAME="SEC16" HREF="vmailmgr-cgi.html#TOC16">4.1 Overview</A></H2>
+
+<P>
+This CGI program can be used to add a user mailbox to a virtual domain.
+
+
+
+
+<H2><A NAME="SEC17" HREF="vmailmgr-cgi.html#TOC17">4.2 Form Configuration</A></H2>
+
+
+
+<H3><A NAME="SEC18" HREF="vmailmgr-cgi.html#TOC18">4.2.1 Required Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        username
+<DT><STRONG>Description:</STRONG>
+<DD>
+The virtual user name of the alias to create.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=username&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        newpass1, newpass2
+<DT><STRONG>Description:</STRONG>
+<DD>
+These two fields specify the new password of the user. They must match
+for the password to be changed. The first eight characters are relevant,
+and may be any combination of letters, digits, or punctuation symbols.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=password name=newpass1&#62;&#60;input type=password name=newpass1&#62;'</SAMP>
+</DL>
+
+
+
+<H3><A NAME="SEC19" HREF="vmailmgr-cgi.html#TOC19">4.2.2 Optional Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        destination
+<DT><STRONG>Description:</STRONG>
+<DD>
+The destination address or addresses to direct a copy of incoming mail,
+separated by commas.
+If an address does not contain a host name (separated from the user name
+with an <SAMP>`@'</SAMP>), it is treated as local to the virtual domain and
+must already exist.
+If this field is not present or blank, no forwarding will be done.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=destination&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        userdir
+<DT><STRONG>Description:</STRONG>
+<DD>
+This field can be used to specify the user mail directory name relative
+to the virtual domain's users directory.
+If this field is not present, the directory name will be the same as the
+user name.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=userdir&#62;'</SAMP>
+</DL>
+
+
+
+<H1><A NAME="SEC20" HREF="vmailmgr-cgi.html#TOC20">5. vchattr</A></H1>
+
+
+
+<H2><A NAME="SEC21" HREF="vmailmgr-cgi.html#TOC21">5.1 Overview</A></H2>
+
+<P>
+This CGI program can be used to change the attributes of an existing
+user in a virtual domain.
+
+
+
+
+<H2><A NAME="SEC22" HREF="vmailmgr-cgi.html#TOC22">5.2 Form Configuration</A></H2>
+
+
+
+<H3><A NAME="SEC23" HREF="vmailmgr-cgi.html#TOC23">5.2.1 Required Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        username
+<DT><STRONG>Description:</STRONG>
+<DD>
+The virtual user name to modify.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=username&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        attribute
+<DT><STRONG>Description:</STRONG>
+<DD>
+The number of the attribute to modify.
+The possible values are:
+<DL COMPACT>
+
+<DT><SAMP>`1'</SAMP>
+<DD>
+The password.
+Use the <TT>`vpasswd'</TT> CGI to do this.
+<DT><SAMP>`2'</SAMP>
+<DD>
+The forwarding destination.
+Use the <TT>`vchforwards'</TT> to do this.
+<DT><SAMP>`3'</SAMP>
+<DD>
+The hard quota.
+<DT><SAMP>`4'</SAMP>
+<DD>
+The soft quota.
+<DT><SAMP>`5'</SAMP>
+<DD>
+The message size limit.
+<DT><SAMP>`6'</SAMP>
+<DD>
+The message count limit.
+<DT><SAMP>`7'</SAMP>
+<DD>
+The account's expiry time.
+<DT><SAMP>`8'</SAMP>
+<DD>
+Set to zero to disable delivery to the account's mailbox (without
+deleting the account).
+Set to non-zero to enable delivery.
+<DT><SAMP>`9'</SAMP>
+<DD>
+The personal information string.
+</DL>
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=hidden name=attribute value=2&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        newvalue
+<DT><STRONG>Description:</STRONG>
+<DD>
+The new value for the given attribute.
+The format of this new value is dependant on the type of the attribute.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=newvalue&#62;'</SAMP>
+</DL>
+
+
+
+<H1><A NAME="SEC24" HREF="vmailmgr-cgi.html#TOC24">6. vchforwards</A></H1>
+
+
+
+<H2><A NAME="SEC25" HREF="vmailmgr-cgi.html#TOC25">6.1 Overview</A></H2>
+
+<P>
+This CGI program can be used to change the forwarding destination of an
+existing user.
+
+
+
+
+<H2><A NAME="SEC26" HREF="vmailmgr-cgi.html#TOC26">6.2 Form Configuration</A></H2>
+
+
+
+<H3><A NAME="SEC27" HREF="vmailmgr-cgi.html#TOC27">6.2.1 Required Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        username
+<DT><STRONG>Description:</STRONG>
+<DD>
+The virtual user name to modify.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=username&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        destination
+<DT><STRONG>Description:</STRONG>
+<DD>
+The destination address or addresses of the alias, separated by commas.
+If an address does not contain a host name (separated from the user name
+with an <SAMP>`@'</SAMP>), it is treated as local to the virtual domain and
+must already exist.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=destination&#62;'</SAMP>
+</DL>
+
+
+
+<H3><A NAME="SEC28" HREF="vmailmgr-cgi.html#TOC28">6.2.2 Optional Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        enable
+<DT><STRONG>Description:</STRONG>
+<DD>
+Set this field to <SAMP>`0'</SAMP> to cause mailbox delivery to this account to
+be disabled after changing the alias.
+Set it to any number except <SAMP>`0'</SAMP> to cause mailbox delivery to be
+enabled before changing the alias.
+If it is not set, the mailbox is neither enabled nor disabled.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;select name=enable&#62;
+&#60;option value=0&#62;Disable
+&#60;option value=1&#62;Enable
+&#60;/select&#62;'</SAMP>
+</DL>
+
+
+
+<H1><A NAME="SEC29" HREF="vmailmgr-cgi.html#TOC29">7. vdeluser</A></H1>
+
+
+
+<H2><A NAME="SEC30" HREF="vmailmgr-cgi.html#TOC30">7.1 Overview</A></H2>
+
+<P>
+This CGI program deletes a user from a virtual domain.
+
+
+
+
+<H2><A NAME="SEC31" HREF="vmailmgr-cgi.html#TOC31">7.2 Form Configuration</A></H2>
+
+
+
+<H3><A NAME="SEC32" HREF="vmailmgr-cgi.html#TOC32">7.2.1 Required Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        username
+<DT><STRONG>Description:</STRONG>
+<DD>
+The virtual user name of the user to delete.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=username&#62;'</SAMP>
+</DL>
+
+
+
+<H1><A NAME="SEC33" HREF="vmailmgr-cgi.html#TOC33">8. vpasswd</A></H1>
+
+
+
+<H2><A NAME="SEC34" HREF="vmailmgr-cgi.html#TOC34">8.1 Overview</A></H2>
+
+<P>
+This CGI program can be used to change the password of a user either by
+the user themself or by the domain administrator.
+
+
+
+
+<H2><A NAME="SEC35" HREF="vmailmgr-cgi.html#TOC35">8.2 Form Configuration</A></H2>
+
+<P>
+The password field used by this CGI may match either the password of the
+virtual domain administrator or that of the user being modified.
+
+
+
+
+<H3><A NAME="SEC36" HREF="vmailmgr-cgi.html#TOC36">8.2.1 Required Form Fields</A></H3>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        username
+<DT><STRONG>Description:</STRONG>
+<DD>
+This field specifies the name of the user that is to be modified.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=text name=username&#62;'</SAMP>
+</DL>
+
+<DL COMPACT>
+
+<DT><STRONG>Field:</STRONG>
+<DD>
+        newpass1, newpass2
+<DT><STRONG>Description:</STRONG>
+<DD>
+These two fields specify the new password of the user.
+They must match for the password to be changed.
+The password may contain any combination of
+letters, digits, or punctuation symbols.
+<DT><STRONG>Syntax:</STRONG>
+<DD>
+<SAMP>`&#60;input type=password name=newpass1&#62; &#60;input type=password name=newpass2&#62;'</SAMP>
+</DL>
+
+<P><HR><P>
+This document was generated on 14 September 2000 using
+<A HREF="http://wwwinfo.cern.ch/dis/texi2html/">texi2html</A>&nbsp;1.56k.
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/vmailmgr-cgi.texi	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,532 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename vmailmgr-cgi.info
+@settitle vmailmgr CGI Documentation
+@setchapternewpage off
+@paragraphindent 5
+@c %**end of header
+@footnotestyle end
+
+@ifinfo
+Copyright @copyright{} 1998 Bruce Guenter
+@end ifinfo
+
+@titlepage
+@title vmailmgr CGI Documentation
+@author Bruce Guenter
+@subtitle @today{}
+@end titlepage
+
+@node Top,  , (dir), (dir)
+
+@c ****************************************************************************
+@chapter Introduction
+
+This is the documentation for the CGI programs for vmailmgr.
+
+@c ============================================================================
+@section Common Form Configuration
+
+The following form fields are common to all of the vmailmgr CGI
+programs.
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        vdomain
+@item Description:
+This field specifies the name of the virtual domain under which to
+perform this operation.
+@item Syntax:
+@samp{<input type=hidden name=vdomain value="@var{domain-name}">}
+or
+@samp{<input type=text name=vdomain>}
+@end table
+
+@table @strong
+@item Field:
+        password
+@item Description:
+Unless noted below, this field specifies the password of the
+administrator for the given virtual domain.
+@item Syntax:
+@samp{<input type=password name=password>}
+@end table
+
+@c ----------------------------------------------------------------------------
+@subsection Optional Form Fields
+
+@table @strong
+@item Field:
+        error_redirect
+@item Description:
+If this field is set, any operation that results in an error will be
+redirected to the given URL.
+If not set, a pre-programmed document (which includes the error message)
+will be output.
+@item Syntax:
+@samp{<input type=hidden name=error_redirect value="@var{URL}">}
+@end table
+
+@table @strong
+@item Field:
+        redirect
+@item Description:
+If this field is set, any operation that completes successfully with be
+redirected to the given URL.
+If not set, a pre-programmed document (which includes the completion
+message) will be output.
+@item Syntax:
+@samp{<input type=hidden name=redirect value="@var{URL}">}
+@end table
+
+@c ****************************************************************************
+@chapter listvdomain
+
+@c ============================================================================
+@section Overview
+
+This CGI program will list the mailboxes and aliases in a virtual domain
+in a three-column table.
+The first column lists the mailbox or alias name,
+the second column is either @samp{Alias} or @samp{Mailbox},
+and the third column lists the destination.
+
+@c ============================================================================
+@section Form Configuration
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+No additional form fields are Required.
+
+@c ----------------------------------------------------------------------------
+@subsection Optional Form Fields
+
+@table @strong
+@item Field:
+        body-flags
+@item Description:
+If present, the contents of this field is inserted into the
+@samp{<body>} tag at the start of the document.
+@item Syntax:
+@samp{<input type=hidden name=body-flags value="bgcolor=ffffff">}
+@end table
+
+@table @strong
+@item Field:
+        cell-align
+@item Description:
+Sets the cell alignment.
+Defaults to @samp{left}.
+@item Syntax:
+@samp{<input type=hidden name=cell-align value=center>}
+@end table
+
+@table @strong
+@item Field:
+        cell-post
+@item Description:
+If present, the contents of this field will be output prior to every
+@samp{</td>} tag.
+@item Syntax:
+@samp{<input type=hidden name=cell-post value="</font>">}
+@end table
+
+@table @strong
+@item Field:
+        cell-pre
+@item Description:
+If present, the contents of this field will be output after every
+@samp{<td>} tag.
+@item Syntax:
+@samp{<input type=hidden name=cell-pre value="<font size=1 name=ariel>">}
+@end table
+
+@table @strong
+@item Field:
+        p-align
+@item Description:
+Sets the default paragraph alignment.
+Defaults to @samp{left}.
+@item Syntax:
+@samp{<input type=hidden name=p-align value=center>}
+@end table
+
+@table @strong
+@item Field:
+        title-post
+@item Description:
+If present, the contents of this field are output after the title text.
+Defaults to @samp{</h1>}.
+@item Syntax:
+@samp{<input type=hidden name=title-post value="</font>">}
+@end table
+
+@table @strong
+@item Field:
+        table-align
+@item Description:
+Sets the allignment of the table listing the users.
+Defaults to @samp{left}.
+@item Syntax:
+@samp{<input type=hidden name=table-align value=center>}
+@end table
+
+@table @strong
+@item Field:
+        title-pre
+@item Description:
+If present, the contents of this field are output before the title text.
+Defaults to @samp{<h1>}.
+@item Syntax:
+@samp{<input type=hidden name=title-pre value="<font size=3 face=verdana>">}
+@end table
+
+@table @strong
+@item Field:
+        userlink
+@item Description:
+If this field is present, all user names will be enclosed in a link to the
+contents of this field.  If the field contains a '%', it will be
+replaced by the user name.
+@item Syntax:
+@samp{<input type=hidden name=userlink value="/cgi-bin/admin-user?name=%">}
+@end table
+
+@c ****************************************************************************
+@chapter vaddalias
+
+@c ============================================================================
+@section Overview
+
+This CGI program can be used to add an alias to a virtual domain.
+
+@c ============================================================================
+@section Form Configuration
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        username
+@item Description:
+The virtual user name of the alias to create.
+@item Syntax:
+@samp{<input type=text name=username>}
+@end table
+
+@table @strong
+@item Field:
+        destination
+@item Description:
+The destination address or addresses of the alias, separated by commas.
+If an address does not contain a host name (separated from the user name
+with an @samp{@@}), it is treated as local to the virtual domain and
+must already exist.
+@item Syntax:
+@samp{<input type=text name=destination>}
+@end table
+
+@c ----------------------------------------------------------------------------
+@subsection Optional Form Fields
+
+@table @strong
+@item Field:
+        newpass1, newpass2
+@item Description:
+These two fields specify the new password of the user. They must match
+for the password to be changed. The first eight characters are relevant,
+and may be any combination of letters, digits, or punctuation symbols.
+If these fields are not present or are empty, a null passcode is used.
+@item Syntax:
+@samp{<input type=password name=newpass1><input type=password name=newpass1>}
+@end table
+
+@c ****************************************************************************
+@chapter vadduser
+
+@c ============================================================================
+@section Overview
+
+This CGI program can be used to add a user mailbox to a virtual domain.
+
+@c ============================================================================
+@section Form Configuration
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        username
+@item Description:
+The virtual user name of the alias to create.
+@item Syntax:
+@samp{<input type=text name=username>}
+@end table
+
+@table @strong
+@item Field:
+        newpass1, newpass2
+@item Description:
+These two fields specify the new password of the user. They must match
+for the password to be changed. The first eight characters are relevant,
+and may be any combination of letters, digits, or punctuation symbols.
+@item Syntax:
+@samp{<input type=password name=newpass1><input type=password name=newpass1>}
+@end table
+
+@c ----------------------------------------------------------------------------
+@subsection Optional Form Fields
+
+@table @strong
+@item Field:
+        destination
+@item Description:
+The destination address or addresses to direct a copy of incoming mail,
+separated by commas.
+If an address does not contain a host name (separated from the user name
+with an @samp{@@}), it is treated as local to the virtual domain and
+must already exist.
+If this field is not present or blank, no forwarding will be done.
+@item Syntax:
+@samp{<input type=text name=destination>}
+@end table
+
+@table @strong
+@item Field:
+        userdir
+@item Description:
+This field can be used to specify the user mail directory name relative
+to the virtual domain's users directory.
+If this field is not present, the directory name will be the same as the
+user name.
+@item Syntax:
+@samp{<input type=text name=userdir>}
+@end table
+
+@c ****************************************************************************
+@chapter vchattr
+
+@c ============================================================================
+@section Overview
+
+This CGI program can be used to change the attributes of an existing
+user in a virtual domain.
+
+@c ============================================================================
+@section Form Configuration
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        username
+@item Description:
+The virtual user name to modify.
+@item Syntax:
+@samp{<input type=text name=username>}
+@end table
+
+@table @strong
+@item Field:
+        attribute
+@item Description:
+The number of the attribute to modify.
+The possible values are:
+@table @samp
+@item 1
+The password.
+Use the @file{vpasswd} CGI to do this.
+@item 2
+The forwarding destination.
+Use the @file{vchforwards} to do this.
+@item 3
+The hard quota.
+@item 4
+The soft quota.
+@item 5
+The message size limit.
+@item 6
+The message count limit.
+@item 7
+The account's expiry time.
+@item 8
+Set to zero to disable delivery to the account's mailbox (without
+deleting the account).
+Set to non-zero to enable delivery.
+@item 9
+The personal information string.
+@end table
+@item Syntax:
+@samp{<input type=hidden name=attribute value=2>}
+@end table
+
+@table @strong
+@item Field:
+        newvalue
+@item Description:
+The new value for the given attribute.
+The format of this new value is dependant on the type of the attribute.
+@item Syntax:
+@samp{<input type=text name=newvalue>}
+@end table
+
+@c ****************************************************************************
+@chapter vchforwards
+
+@c ============================================================================
+@section Overview
+
+This CGI program can be used to change the forwarding destination of an
+existing user.
+
+@c ============================================================================
+@section Form Configuration
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        username
+@item Description:
+The virtual user name to modify.
+@item Syntax:
+@samp{<input type=text name=username>}
+@end table
+
+@table @strong
+@item Field:
+        destination
+@item Description:
+The destination address or addresses of the alias, separated by commas.
+If an address does not contain a host name (separated from the user name
+with an @samp{@@}), it is treated as local to the virtual domain and
+must already exist.
+@item Syntax:
+@samp{<input type=text name=destination>}
+@end table
+
+@c ----------------------------------------------------------------------------
+@subsection Optional Form Fields
+
+@table @strong
+@item Field:
+        enable
+@item Description:
+Set this field to @samp{0} to cause mailbox delivery to this account to
+be disabled after changing the alias.
+Set it to any number except @samp{0} to cause mailbox delivery to be
+enabled before changing the alias.
+If it is not set, the mailbox is neither enabled nor disabled.
+@item Syntax:
+@samp{<select name=enable>
+<option value=0>Disable
+<option value=1>Enable
+</select>}
+@end table
+
+@c ****************************************************************************
+@chapter vdeluser
+
+@c ============================================================================
+@section Overview
+
+This CGI program deletes a user from a virtual domain.
+
+@c ============================================================================
+@section Form Configuration
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        username
+@item Description:
+The virtual user name of the user to delete.
+@item Syntax:
+@samp{<input type=text name=username>}
+@end table
+
+@c ****************************************************************************
+@chapter vpasswd
+
+@c ============================================================================
+@section Overview
+
+This CGI program can be used to change the password of a user either by
+the user themself or by the domain administrator.
+
+@c ============================================================================
+@section Form Configuration
+
+The password field used by this CGI may match either the password of the
+virtual domain administrator or that of the user being modified.
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        username
+@item Description:
+This field specifies the name of the user that is to be modified.
+@item Syntax:
+@samp{<input type=text name=username>}
+@end table
+
+@table @strong
+@item Field:
+        newpass1, newpass2
+@item Description:
+These two fields specify the new password of the user.
+They must match for the password to be changed.
+The password may contain any combination of
+letters, digits, or punctuation symbols.
+@item Syntax:
+@samp{<input type=password name=newpass1> <input type=password name=newpass2>}
+@end table
+
+@c ****************************************************************************
+@contents
+
+@bye
+
+@c ****************************************************************************
+@chapter template
+
+@c ============================================================================
+@section Overview
+
+This CGI program ...
+
+@c ============================================================================
+@section Form Configuration
+
+@c ----------------------------------------------------------------------------
+@subsection Required Form Fields
+
+@table @strong
+@item Field:
+        fieldname
+@item Description:
+@item Syntax:
+@end table
+
+@c ----------------------------------------------------------------------------
+@subsection Optional Form Fields
+
+@table @strong
+@item Field:
+        fieldname
+@item Description:
+@item Syntax:
+@end table
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/vmailmgr-cgi.txt	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,433 @@
+
+                          vmailmgr CGI Documentation
+                                       
+14 September 2000
+
+   
+    Bruce Guenter
+     _________________________________________________________________
+   
+                               Table of Contents
+                                       
+     * 1. Introduction
+          + 1.1 Common Form Configuration
+               o 1.1.1 Required Form Fields
+               o 1.1.2 Optional Form Fields
+     * 2. listvdomain
+          + 2.1 Overview
+          + 2.2 Form Configuration
+               o 2.2.1 Required Form Fields
+               o 2.2.2 Optional Form Fields
+     * 3. vaddalias
+          + 3.1 Overview
+          + 3.2 Form Configuration
+               o 3.2.1 Required Form Fields
+               o 3.2.2 Optional Form Fields
+     * 4. vadduser
+          + 4.1 Overview
+          + 4.2 Form Configuration
+               o 4.2.1 Required Form Fields
+               o 4.2.2 Optional Form Fields
+     * 5. vchattr
+          + 5.1 Overview
+          + 5.2 Form Configuration
+               o 5.2.1 Required Form Fields
+     * 6. vchforwards
+          + 6.1 Overview
+          + 6.2 Form Configuration
+               o 6.2.1 Required Form Fields
+               o 6.2.2 Optional Form Fields
+     * 7. vdeluser
+          + 7.1 Overview
+          + 7.2 Form Configuration
+               o 7.2.1 Required Form Fields
+     * 8. vpasswd
+          + 8.1 Overview
+          + 8.2 Form Configuration
+               o 8.2.1 Required Form Fields
+     _________________________________________________________________
+   
+                                1. Introduction
+                                       
+   This is the documentation for the CGI programs for vmailmgr.
+   
+1.1 Common Form Configuration
+
+   The following form fields are common to all of the vmailmgr CGI
+   programs.
+   
+  1.1.1 Required Form Fields
+  
+   Field:
+          vdomain
+   Description:
+          This field specifies the name of the virtual domain under which
+          to perform this operation.
+   Syntax:
+          `<input type=hidden name=vdomain value="domain-name">' or
+          `<input type=text name=vdomain>'
+          
+   Field:
+          password
+   Description:
+          Unless noted below, this field specifies the password of the
+          administrator for the given virtual domain.
+   Syntax:
+          `<input type=password name=password>'
+          
+  1.1.2 Optional Form Fields
+  
+   Field:
+          error_redirect
+   Description:
+          If this field is set, any operation that results in an error
+          will be redirected to the given URL. If not set, a
+          pre-programmed document (which includes the error message) will
+          be output.
+   Syntax:
+          `<input type=hidden name=error_redirect value="URL">'
+          
+   Field:
+          redirect
+   Description:
+          If this field is set, any operation that completes successfully
+          with be redirected to the given URL. If not set, a
+          pre-programmed document (which includes the completion message)
+          will be output.
+   Syntax:
+          `<input type=hidden name=redirect value="URL">'
+          
+                                2. listvdomain
+                                       
+2.1 Overview
+
+   This CGI program will list the mailboxes and aliases in a virtual
+   domain in a three-column table. The first column lists the mailbox or
+   alias name, the second column is either `Alias' or `Mailbox', and the
+   third column lists the destination.
+   
+2.2 Form Configuration
+
+  2.2.1 Required Form Fields
+  
+   No additional form fields are Required.
+   
+  2.2.2 Optional Form Fields
+  
+   Field:
+          body-flags
+   Description:
+          If present, the contents of this field is inserted into the
+          `<body>' tag at the start of the document.
+   Syntax:
+          `<input type=hidden name=body-flags value="bgcolor=ffffff">'
+          
+   Field:
+          cell-align
+   Description:
+          Sets the cell alignment. Defaults to `left'.
+   Syntax:
+          `<input type=hidden name=cell-align value=center>'
+          
+   Field:
+          cell-post
+   Description:
+          If present, the contents of this field will be output prior to
+          every `</td>' tag.
+   Syntax:
+          `<input type=hidden name=cell-post value="</font>">'
+          
+   Field:
+          cell-pre
+   Description:
+          If present, the contents of this field will be output after
+          every `<td>' tag.
+   Syntax:
+          `<input type=hidden name=cell-pre value="<font size=1
+          name=ariel>">'
+          
+   Field:
+          p-align
+   Description:
+          Sets the default paragraph alignment. Defaults to `left'.
+   Syntax:
+          `<input type=hidden name=p-align value=center>'
+          
+   Field:
+          title-post
+   Description:
+          If present, the contents of this field are output after the
+          title text. Defaults to `</h1>'.
+   Syntax:
+          `<input type=hidden name=title-post value="</font>">'
+          
+   Field:
+          table-align
+   Description:
+          Sets the allignment of the table listing the users. Defaults to
+          `left'.
+   Syntax:
+          `<input type=hidden name=table-align value=center>'
+          
+   Field:
+          title-pre
+   Description:
+          If present, the contents of this field are output before the
+          title text. Defaults to `<h1>'.
+   Syntax:
+          `<input type=hidden name=title-pre value="<font size=3
+          face=verdana>">'
+          
+   Field:
+          userlink
+   Description:
+          If this field is present, all user names will be enclosed in a
+          link to the contents of this field. If the field contains a
+          '%', it will be replaced by the user name.
+   Syntax:
+          `<input type=hidden name=userlink
+          value="/cgi-bin/admin-user?name=%">'
+          
+                                 3. vaddalias
+                                       
+3.1 Overview
+
+   This CGI program can be used to add an alias to a virtual domain.
+   
+3.2 Form Configuration
+
+  3.2.1 Required Form Fields
+  
+   Field:
+          username
+   Description:
+          The virtual user name of the alias to create.
+   Syntax:
+          `<input type=text name=username>'
+          
+   Field:
+          destination
+   Description:
+          The destination address or addresses of the alias, separated by
+          commas. If an address does not contain a host name (separated
+          from the user name with an `@'), it is treated as local to the
+          virtual domain and must already exist.
+   Syntax:
+          `<input type=text name=destination>'
+          
+  3.2.2 Optional Form Fields
+  
+   Field:
+          newpass1, newpass2
+   Description:
+          These two fields specify the new password of the user. They
+          must match for the password to be changed. The first eight
+          characters are relevant, and may be any combination of letters,
+          digits, or punctuation symbols. If these fields are not present
+          or are empty, a null passcode is used.
+   Syntax:
+          `<input type=password name=newpass1><input type=password
+          name=newpass1>'
+          
+                                  4. vadduser
+                                       
+4.1 Overview
+
+   This CGI program can be used to add a user mailbox to a virtual
+   domain.
+   
+4.2 Form Configuration
+
+  4.2.1 Required Form Fields
+  
+   Field:
+          username
+   Description:
+          The virtual user name of the alias to create.
+   Syntax:
+          `<input type=text name=username>'
+          
+   Field:
+          newpass1, newpass2
+   Description:
+          These two fields specify the new password of the user. They
+          must match for the password to be changed. The first eight
+          characters are relevant, and may be any combination of letters,
+          digits, or punctuation symbols.
+   Syntax:
+          `<input type=password name=newpass1><input type=password
+          name=newpass1>'
+          
+  4.2.2 Optional Form Fields
+  
+   Field:
+          destination
+   Description:
+          The destination address or addresses to direct a copy of
+          incoming mail, separated by commas. If an address does not
+          contain a host name (separated from the user name with an `@'),
+          it is treated as local to the virtual domain and must already
+          exist. If this field is not present or blank, no forwarding
+          will be done.
+   Syntax:
+          `<input type=text name=destination>'
+          
+   Field:
+          userdir
+   Description:
+          This field can be used to specify the user mail directory name
+          relative to the virtual domain's users directory. If this field
+          is not present, the directory name will be the same as the user
+          name.
+   Syntax:
+          `<input type=text name=userdir>'
+          
+                                  5. vchattr
+                                       
+5.1 Overview
+
+   This CGI program can be used to change the attributes of an existing
+   user in a virtual domain.
+   
+5.2 Form Configuration
+
+  5.2.1 Required Form Fields
+  
+   Field:
+          username
+   Description:
+          The virtual user name to modify.
+   Syntax:
+          `<input type=text name=username>'
+          
+   Field:
+          attribute
+   Description:
+          The number of the attribute to modify. The possible values are:
+        `1'
+               The password. Use the `vpasswd' CGI to do this.
+        `2'
+               The forwarding destination. Use the `vchforwards' to do
+               this.
+        `3'
+               The hard quota.
+        `4'
+               The soft quota.
+        `5'
+               The message size limit.
+        `6'
+               The message count limit.
+        `7'
+               The account's expiry time.
+        `8'
+               Set to zero to disable delivery to the account's mailbox
+               (without deleting the account). Set to non-zero to enable
+               delivery.
+        `9'
+               The personal information string.
+   Syntax:
+          `<input type=hidden name=attribute value=2>'
+          
+   Field:
+          newvalue
+   Description:
+          The new value for the given attribute. The format of this new
+          value is dependant on the type of the attribute.
+   Syntax:
+          `<input type=text name=newvalue>'
+          
+                                6. vchforwards
+                                       
+6.1 Overview
+
+   This CGI program can be used to change the forwarding destination of
+   an existing user.
+   
+6.2 Form Configuration
+
+  6.2.1 Required Form Fields
+  
+   Field:
+          username
+   Description:
+          The virtual user name to modify.
+   Syntax:
+          `<input type=text name=username>'
+          
+   Field:
+          destination
+   Description:
+          The destination address or addresses of the alias, separated by
+          commas. If an address does not contain a host name (separated
+          from the user name with an `@'), it is treated as local to the
+          virtual domain and must already exist.
+   Syntax:
+          `<input type=text name=destination>'
+          
+  6.2.2 Optional Form Fields
+  
+   Field:
+          enable
+   Description:
+          Set this field to `0' to cause mailbox delivery to this account
+          to be disabled after changing the alias. Set it to any number
+          except `0' to cause mailbox delivery to be enabled before
+          changing the alias. If it is not set, the mailbox is neither
+          enabled nor disabled.
+   Syntax:
+          `<select name=enable> <option value=0>Disable <option
+          value=1>Enable </select>'
+          
+                                  7. vdeluser
+                                       
+7.1 Overview
+
+   This CGI program deletes a user from a virtual domain.
+   
+7.2 Form Configuration
+
+  7.2.1 Required Form Fields
+  
+   Field:
+          username
+   Description:
+          The virtual user name of the user to delete.
+   Syntax:
+          `<input type=text name=username>'
+          
+                                  8. vpasswd
+                                       
+8.1 Overview
+
+   This CGI program can be used to change the password of a user either
+   by the user themself or by the domain administrator.
+   
+8.2 Form Configuration
+
+   The password field used by this CGI may match either the password of
+   the virtual domain administrator or that of the user being modified.
+   
+  8.2.1 Required Form Fields
+  
+   Field:
+          username
+   Description:
+          This field specifies the name of the user that is to be
+          modified.
+   Syntax:
+          `<input type=text name=username>'
+          
+   Field:
+          newpass1, newpass2
+   Description:
+          These two fields specify the new password of the user. They
+          must match for the password to be changed. The password may
+          contain any combination of letters, digits, or punctuation
+          symbols.
+   Syntax:
+          `<input type=password name=newpass1> <input type=password
+          name=newpass2>'
+     _________________________________________________________________
+   
+   This document was generated on 14 September 2000 using
+   texi2html 1.56k.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/vmailmgr.7	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,245 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH vmailmgr 7 "vmailmgr 0.96.9" "2000-09-30" "VMailMgr Tools Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+vmailmgr \- a package to manage virtual mailboxes and aliases
+.SH "DESCRIPTION"
+This document describes the vmailmgr package which contains, among other
+things, a virtualizing password
+checking interface for qmail-pop3d.
+It is intended as a drop-in replacement for the standard checkpassword
+utility with several significant enhancements.
+.PP
+One of the goals of building this package was to provide a usable virtual
+mail interface that was efficient and as fully integrated into qmail as
+possible.
+This means that this package attempts to use the same control files that
+qmail uses to determine if a user is logging in via a virtual host.
+It also implies that all programs should be compiled for two reasons:
+.Ip "1" 8
+Compiled code will be more efficient than code executed by an
+interpreter, such as perl or java
+.Ip "2" 8
+There is no need for an
+interpreter to reside on the system once the code is compiled, eliminating
+concerns that such an interpreter could be used as an exploit in itself.
+.SH "SEE ALSO"
+\fIcheckvpw\fR\|(8),
+\fIvaddalias\fR\|(1),
+\fIvadduser\fR\|(1),
+\fIvdelalias\fR\|(1),
+\fIvdeliver\fR\|(1),
+\fIvdeluser\fR\|(1),
+\fIvmailmgrd\fR\|(8),
+\fIvpasswd\fR\|(1),
+\fIvsetup\fR\|(1)
+.SH "AUTHOR"
+Bruce Guenter <\fIbruceg@em.ca\fR>.
+.SH "HISTORY"
+\fBvmailmgr\fR used to be called \fBcheckvpw\fR, named for the original
+\*(L"core\*(R" of the package.
+
+.rn }` ''
+.IX Title "vmailmgr 7"
+.IX Name "vmailmgr - a package to manage virtual mailboxes and aliases"
+
+.IX Header "NAME"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "1"
+
+.IX Item "2"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHOR"
+
+.IX Header "HISTORY"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/vmailmgr.html	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,79 @@
+<HTML>
+<HEAD>
+<TITLE>vmailmgr - a package to manage virtual mailboxes and aliases</TITLE>
+<LINK REV="made" HREF="mailto:root@porky.devel.redhat.com">
+</HEAD>
+
+<BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+	<LI><A HREF="#NAME">NAME</A>
+	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+	<LI><A HREF="#AUTHOR">AUTHOR</A>
+	<LI><A HREF="#HISTORY">HISTORY</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME</A></H1>
+<P>
+vmailmgr - a package to manage virtual mailboxes and aliases
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
+<P>
+This document describes the vmailmgr package which contains, among other
+things, a virtualizing password checking interface for qmail-pop3d. It is
+intended as a drop-in replacement for the standard checkpassword utility
+with several significant enhancements.
+
+<P>
+One of the goals of building this package was to provide a usable virtual
+mail interface that was efficient and as fully integrated into qmail as
+possible. This means that this package attempts to use the same control
+files that qmail uses to determine if a user is logging in via a virtual
+host. It also implies that all programs should be compiled for two reasons:
+
+<OL>
+<LI>
+<P>
+Compiled code will be more efficient than code executed by an interpreter,
+such as perl or java
+
+<LI>
+<P>
+There is no need for an interpreter to reside on the system once the code
+is compiled, eliminating concerns that such an interpreter could be used as
+an exploit in itself.
+
+</OL>
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
+<P>
+<CODE>checkvpw(8),</CODE> <CODE>vaddalias(1),</CODE>
+<CODE>vadduser(1),</CODE> <CODE>vdelalias(1),</CODE>
+<CODE>vdeliver(1),</CODE> <CODE>vdeluser(1),</CODE>
+<CODE>vmailmgrd(8),</CODE> <CODE>vpasswd(1),</CODE> <CODE>vsetup(1)</CODE>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR</A></H1>
+<P>
+Bruce Guenter &lt;<EM>bruceg@em.ca</EM>&gt;.
+
+<P>
+<HR>
+<H1><A NAME="HISTORY">HISTORY</A></H1>
+<P>
+<STRONG>vmailmgr</STRONG> used to be called <STRONG>checkvpw</STRONG>, named for the original ``core'' of the package.
+</BODY>
+
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/vmailmgr.pod	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,54 @@
+=head1 NAME
+
+vmailmgr - a package to manage virtual mailboxes and aliases
+
+=head1 DESCRIPTION
+
+This document describes the vmailmgr package which contains, among other
+things, a virtualizing password
+checking interface for qmail-pop3d.
+It is intended as a drop-in replacement for the standard checkpassword
+utility with several significant enhancements.
+
+One of the goals of building this package was to provide a usable virtual
+mail interface that was efficient and as fully integrated into qmail as
+possible.
+This means that this package attempts to use the same control files that
+qmail uses to determine if a user is logging in via a virtual host.
+It also implies that all programs should be compiled for two reasons:
+
+=over 8
+
+=item 1
+
+Compiled code will be more efficient than code executed by an
+interpreter, such as perl or java
+
+=item 2
+
+There is no need for an
+interpreter to reside on the system once the code is compiled, eliminating
+concerns that such an interpreter could be used as an exploit in itself.
+
+=back
+
+=head1 SEE ALSO
+
+checkvpw(8),
+vaddalias(1),
+vadduser(1),
+vdelalias(1),
+vdeliver(1),
+vdeluser(1),
+vmailmgrd(8),
+vpasswd(1),
+vsetup(1)
+
+=head1 AUTHOR
+
+Bruce Guenter <F<bruceg@em.ca>>.
+
+=head1 HISTORY
+
+B<vmailmgr> used to be called B<checkvpw>, named for the original
+"core" of the package.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install-sh	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,23 @@
+SUBDIRS = misc vdomain vpwentry vpwtable cdb++ cgi cli fdbuf mystring config \
+	courier-authlib
+noinst_LIBRARIES = libvmailmgr.a libcgi.a libcli.a
+EXTRA_DIST = mergelib.sh
+
+libvmailmgr_a_SOURCES=
+libvmailmgr.a: mergelib.sh cdb++/libcdb++.a misc/libmisc.a \
+	config/libconfig.a vpwentry/libvpwentry.a vpwtable/libvpwtable.a \
+	vdomain/libvdomain.a fdbuf/libfdbuf.a mystring/libmystring.a
+	$(RM) -f $@
+	sh mergelib.sh $@ cdb++/libcdb++.a misc/libmisc.a \
+	config/libconfig.a vpwentry/libvpwentry.a vpwtable/libvpwtable.a \
+	vdomain/libvdomain.a fdbuf/libfdbuf.a mystring/libmystring.a
+	
+libcli_a_SOURCES =
+libcli.a: cli/libcli.a mergelib.sh
+	$(RM) -f $@
+	sh mergelib.sh $@ cli/libcli.a
+
+libcgi_a_SOURCES =
+libcgi.a: cgi/libcgi.a mergelib.sh
+	$(RM) -f $@
+	sh mergelib.sh $@ cgi/libcgi.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,365 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+SUBDIRS = misc vdomain vpwentry vpwtable cdb++ cgi cli fdbuf mystring config 	courier-authlib
+
+noinst_LIBRARIES = libvmailmgr.a libcgi.a libcli.a
+EXTRA_DIST = mergelib.sh
+
+libvmailmgr_a_SOURCES = 
+
+libcli_a_SOURCES = 
+
+libcgi_a_SOURCES = 
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libvmailmgr_a_LIBADD = 
+libvmailmgr_a_OBJECTS = 
+libcgi_a_LIBADD = 
+libcgi_a_OBJECTS = 
+libcli_a_LIBADD = 
+libcli_a_OBJECTS = 
+AR = ar
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libvmailmgr_a_SOURCES) $(libcgi_a_SOURCES) $(libcli_a_SOURCES)
+OBJECTS = $(libvmailmgr_a_OBJECTS) $(libcgi_a_OBJECTS) $(libcli_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive  \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+	@set fnord $(MAKEFLAGS); amf=$$2; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@set fnord $(MAKEFLAGS); amf=$$2; \
+	dot_seen=no; \
+	rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+	  rev="$$subdir $$rev"; \
+	  test "$$subdir" = "." && dot_seen=yes; \
+	done; \
+	test "$$dot_seen" = "no" && rev=". $$rev"; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+	    test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+	for subdir in $(SUBDIRS); do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d $(distdir)/$$subdir \
+	    || mkdir $(distdir)/$$subdir \
+	    || exit 1; \
+	    chmod 777 $(distdir)/$$subdir; \
+	    (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am: all-am
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+install-exec-am:
+install-exec: install-exec-recursive
+
+install-data-am:
+install-data: install-data-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am:
+uninstall: uninstall-recursive
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-recursive
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile install-data-recursive \
+uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs-am \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+libvmailmgr.a: mergelib.sh cdb++/libcdb++.a misc/libmisc.a \
+	config/libconfig.a vpwentry/libvpwentry.a vpwtable/libvpwtable.a \
+	vdomain/libvdomain.a fdbuf/libfdbuf.a mystring/libmystring.a
+	$(RM) -f $@
+	sh mergelib.sh $@ cdb++/libcdb++.a misc/libmisc.a \
+	config/libconfig.a vpwentry/libvpwentry.a vpwtable/libvpwtable.a \
+	vdomain/libvdomain.a fdbuf/libfdbuf.a mystring/libmystring.a
+libcli.a: cli/libcli.a mergelib.sh
+	$(RM) -f $@
+	sh mergelib.sh $@ cli/libcli.a
+libcgi.a: cgi/libcgi.a mergelib.sh
+	$(RM) -f $@
+	sh mergelib.sh $@ cgi/libcgi.a
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/ac/dirent.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,17 @@
+#include <sys/types.h>
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/ac/time.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/ac/wait.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include <sys/types.h>
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/ChangeLog	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,48 @@
+1999-05-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cdb_writer.cc (cdb_writer): Added "mode" parameter, passed to
+	the fdobuf constructor, to set the file permissions.
+
+1999-04-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cdb_reader.cc: Converted to using fdbuf routines.
+
+	* cdb_get.cc: Converted to using fdbuf routines.
+
+	* cdb_writer.cc: Converted to using fdbuf routines.
+
+1999-03-19  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* internal.h: Renamed cdb_internal.h to this.
+
+1999-03-18  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cdb_internal.h: Moved several internal functions into here
+	instead of in the main header file; fixed some signed char
+	conversion bugs.
+
+	* cdb_get.cc (seek): Typo: & should have been *.
+	(seek): Don't reassign value of "pos" until after its used to set
+	lenhash.
+
+1999-03-16  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cdb_writer.cc (abort): Protect the close and unlink calls
+	against repeated or extraneous calls, to prevent unlinking an
+	existing temporary file.
+
+	* cdb_writer.cc: These routines now call the new C++ cdbmake
+	routines.
+
+	* cdb_make.cc: Copied the contents of cdb-0.55/cdbmake_*.c into
+	here and converted into C++ style code.
+
+1999-03-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cdb_getrec.cc (cdb_getrec): Simply call cdb_reader::get in this
+	function.
+
+	* cdb_get.cc (get): Moved all of cdb_getrec into cdb_reader::get
+	and cdb_reader::seek, and optimized it for multiple reads (only
+	read the header once and store it).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,16 @@
+noinst_LIBRARIES = libcdb++.a
+EXTRA_DIST = ChangeLog cdbtest.cc
+
+INCLUDES = -I..
+
+test: cdbtest
+cdbtest: cdbtest.o libcdb++.a
+	$(CXX) $(CXXFLAGS) -o cdbtest cdbtest.o -L../misc -lmisc -L../mystring -lmystring -L. -lcdb++
+cdbtest.o: cdbtest.cc cdb++.h
+
+libcdb___a_SOURCES = \
+	cdb++.h internal.h datum.h datum.cc \
+	cdb_reader.cc cdb_writer.cc \
+	cdb_getrec.cc cdb_get.cc cdb_make.cc
+
+CLEANFILES = cdbtest.o cdbtest
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,317 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libcdb++.a
+EXTRA_DIST = ChangeLog cdbtest.cc
+
+INCLUDES = -I..
+
+libcdb___a_SOURCES =  	cdb++.h internal.h datum.h datum.cc 	cdb_reader.cc cdb_writer.cc 	cdb_getrec.cc cdb_get.cc cdb_make.cc
+
+
+CLEANFILES = cdbtest.o cdbtest
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libcdb___a_LIBADD = 
+libcdb___a_OBJECTS =  datum.o cdb_reader.o cdb_writer.o cdb_getrec.o \
+cdb_get.o cdb_make.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  ChangeLog Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libcdb___a_SOURCES)
+OBJECTS = $(libcdb___a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/cdb++/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libcdb++.a: $(libcdb___a_OBJECTS) $(libcdb___a_DEPENDENCIES)
+	-rm -f libcdb++.a
+	$(AR) cru libcdb++.a $(libcdb___a_OBJECTS) $(libcdb___a_LIBADD)
+	$(RANLIB) libcdb++.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/cdb++
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+cdb_get.o: cdb_get.cc cdb++.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../cdb++/datum.h \
+	../fdbuf/fdbuf.h ../../config.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h internal.h
+cdb_getrec.o: cdb_getrec.cc cdb++.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+cdb_make.o: cdb_make.cc cdb++.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../cdb++/datum.h \
+	../fdbuf/fdbuf.h ../../config.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h internal.h
+cdb_reader.o: cdb_reader.cc cdb++.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h internal.h
+cdb_writer.o: cdb_writer.cc cdb++.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h internal.h
+datum.o: datum.cc datum.h ../fdbuf/fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+test: cdbtest
+cdbtest: cdbtest.o libcdb++.a
+	$(CXX) $(CXXFLAGS) -o cdbtest cdbtest.o -L../misc -lmisc -L../mystring -lmystring -L. -lcdb++
+cdbtest.o: cdbtest.cc cdb++.h
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/cdb++.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,114 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef CDBXX__CDBXX__H__
+#define CDBXX__CDBXX__H__
+
+#include "mystring/mystring.h"
+#include "cdb++/datum.h"
+#include "fdbuf/fdbuf.h"
+
+typedef unsigned long uint32;
+
+#define CDBMAKE_HPLIST 1000
+
+class cdb_reader
+{
+private:
+  fdibuf in;
+  uint32 eod;
+  uint32 pos;
+  bool failed;
+  bool eof;
+
+  unsigned char header[2048];
+  
+  void abort();
+  int seek(const mystring& key, uint32& len);
+public:
+  cdb_reader(const mystring& filename);
+  ~cdb_reader();
+
+  bool firstrec();
+  datum* nextrec();
+  datum* get(const mystring& key);
+  bool operator!() const
+    {
+      return failed;
+    }
+  operator bool() const
+    {
+      return !failed;
+    }
+};
+
+struct cdbmake {
+  struct hp 
+  {
+    uint32 h;
+    uint32 p;
+  };
+  
+  struct hplist 
+  {
+    cdbmake::hp hp[CDBMAKE_HPLIST];
+    hplist* next;
+    int num;
+  };
+  
+  unsigned char final[2048];
+  uint32 count[256];
+  uint32 start[256];
+  hplist *head;
+  hp *split;
+  hp *hash;
+  uint32 numentries;
+
+  cdbmake();
+  ~cdbmake();
+  int add(uint32 h, uint32 p);
+  int split_hashes();
+  uint32 throw_hash(uint32 pos, int b);
+};
+
+class cdb_writer
+{
+private:
+  fdobuf out;
+  cdbmake cdbm;
+  mystring fntemp;
+  uint32 pos;
+  bool failed;
+  
+  void abort();
+public:
+  cdb_writer(const mystring& filename, int mode = 0666);
+  ~cdb_writer();
+  bool put(const mystring& key, const mystring& data);
+  bool end(const mystring& filename);
+  bool operator!() const
+    {
+      return failed;
+    }
+  operator bool() const
+    {
+      return !failed;
+    }
+};
+
+extern datum* cdb_getrec(const mystring& filename, const mystring& key);
+
+#endif // CDBXX__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/cdb_get.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,87 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "cdb++.h"
+#include "internal.h"
+
+static int match(fdibuf& in, const mystring& key)
+{
+  unsigned len = key.length();
+  const char* keyptr = key.c_str();
+  
+  while (len > 0) {
+    char buf[32];
+    unsigned n = sizeof buf;
+    if(n > len) n = len;
+    if(!in.read(buf, n)) return -1;
+    for(unsigned i = 0;i < n;++i)
+      if(buf[i] != keyptr[i]) return 0;
+    keyptr += n;
+    len -= n;
+  }
+  return 1;
+}
+
+int cdb_reader::seek(const mystring& key, uint32& dlen)
+{
+  if(failed)
+    return -1;
+  uint32 h = hash(key);
+  uint32 pos = 8 * (h & 255);
+
+  uint32 poshash = unpack(header+pos); 
+  uint32 lenhash = unpack(header+pos+4);
+  
+  if(!lenhash) return 0;
+  uint32 h2 = (h >> 8) % lenhash;
+
+  for (uint32 loop = 0; loop < lenhash; ++loop) {
+    if(!in.seek(poshash+8*h2)) return -1;
+    unsigned char packbuf[8];
+    if(!in.read(packbuf, 8)) return -1;
+    uint32 poskd = unpack(packbuf + 4);
+    if(!poskd) return 0;
+    if(unpack(packbuf) == h) {
+      if(!in.seek(poskd)) return -1;
+      if(!in.read(packbuf, 8)) return -1;
+      if(unpack(packbuf) == key.length())
+	switch(match(in, key)) {
+	case -1:
+	  return -1;
+	case 1:
+	  dlen = unpack(packbuf + 4);
+	  return 1;
+	}
+    }
+    if(++h2 == lenhash) h2 = 0;
+  }
+  return 0;
+}
+
+datum* cdb_reader::get(const mystring& key)
+{
+  if(failed)
+    return 0;
+  uint32 len;
+  switch(seek(key, len)) {
+  case -1: return 0;
+  case 0:  return 0;
+  }
+  // Big assume: data is relatively small (will fit on stack)
+  char buf[len];
+  datum* d = !in.read(buf, len) ? 0 : new datum(key, mystring(buf, len));
+  return d;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/cdb_getrec.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,23 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "cdb++.h"
+
+datum* cdb_getrec(const mystring& filename, const mystring& key)
+{
+  cdb_reader cdb(filename);
+  return cdb.get(key);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/cdb_make.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,118 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "cdb++.h"
+#include "internal.h"
+
+cdbmake::cdbmake()
+  : head(0), split(0), hash(0), numentries(0)
+{
+}
+
+cdbmake::~cdbmake()
+{
+  delete[] split;
+  hplist* x = head;
+  while(x) {
+    hplist* next = x->next;
+    delete x;
+    x = next;
+  }
+}
+
+int cdbmake::add(uint32 h, uint32 p)
+{
+  hplist *chead = head;
+
+  if (!chead || (chead->num >= CDBMAKE_HPLIST)) {
+    chead = new hplist;
+    if (!chead) return 0;
+    chead->num = 0;
+    chead->next = head;
+    head = chead;
+  }
+  chead->hp[chead->num].h = h;
+  chead->hp[chead->num].p = p;
+  ++chead->num;
+  ++numentries;
+  return 1;
+}
+
+int cdbmake::split_hashes()
+{
+  for (int i = 0; i < 256; ++i)
+    count[i] = 0;
+
+  for (hplist* x = head; x; x = x->next) {
+    for(int i = x->num; i--; )
+      ++count[255 & x->hp[i].h];
+  }
+
+  uint32 memsize = 1;
+  for (int i = 0; i < 256; ++i) {
+    uint32 u = count[i] * 2;
+    if (u > memsize)
+      memsize = u;
+  }
+
+  memsize += numentries;	// no overflow possible up to now
+  uint32 u = (uint32) 0 - (uint32) 1;
+  u /= sizeof(hp);
+  if (memsize > u) return 0;
+
+  split = new hp[memsize];
+  if (!split) return 0;
+
+  hash = split + numentries;
+
+  u = 0;
+  for (int i = 0;i < 256;++i) {
+    u += count[i];		// bounded by numentries, so no overflow
+    start[i] = u;
+  }
+
+  for (hplist* x = head; x; x = x->next) {
+    int i = x->num;
+    while (i--)
+      split[--start[255 & x->hp[i].h]] = x->hp[i];
+  }
+
+  return 1;
+}
+
+uint32 cdbmake::throw_hash(uint32 pos, int b)
+{
+  uint32 c = count[b];
+  uint32 len = c + c;		// no overflow possible
+  pack(final + 8 * b, pos);
+  pack(final + 8 * b + 4, len);
+
+  if (len) {
+    for (uint32 j = 0; j < len; ++j)
+      hash[j].h = hash[j].p = 0;
+
+    hp* hp = split + start[b];
+    for (uint32 j = 0; j < count[b]; ++j) {
+      uint32 where = (hp->h >> 8) % len;
+      while (hash[where].p)
+	if (++where == len)
+	  where = 0;
+      hash[where] = *hp++;
+    }
+  }
+
+  return len;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/cdb_reader.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,81 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "cdb++.h"
+#include "internal.h"
+
+#define FAIL do{ abort(); return 0; }while(0)
+
+inline uint32 max(uint32 a, uint32 b)
+{
+  return a > b ? a : b;
+}
+
+cdb_reader::cdb_reader(const mystring& filename)
+  : in(filename.c_str()),
+    failed(!in),
+    eof(false)
+{
+  firstrec();
+}
+
+cdb_reader::~cdb_reader()
+{
+}
+
+void cdb_reader::abort()
+{
+  failed = true;
+  in.close();
+}
+
+bool cdb_reader::firstrec()
+{
+  if(failed) return false;
+  if(!in.seek(0) || !in.read(header, 2048)) {
+    abort();
+    return false;
+  }
+  eof = false;
+  eod = unpack(header);
+  pos = 2048;
+  return true;
+}
+
+datum* cdb_reader::nextrec()
+{
+  if(eof) return 0;
+  if(pos >= eod) {
+    eof = true;
+    return 0;
+  }
+  if(failed || eod-pos < 8 || !in.seek(pos)) FAIL;
+  pos += 8;
+  unsigned char buf[8];
+  if(!in.read(buf, 8)) FAIL;
+  uint32 klen = unpack(buf);
+  uint32 dlen = unpack(buf+4);
+  if (eod - pos < klen) FAIL;
+  pos += klen;
+  if (eod - pos < dlen) FAIL;
+  pos += dlen;
+  char tmp[max(klen, dlen)];
+  if(!in.read(tmp, klen)) FAIL;
+  mystring key(tmp, klen);
+  if(!in.read(tmp, dlen)) FAIL;
+  mystring data(tmp, dlen);
+  return new datum(key, data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/cdb_writer.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,92 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <stdio.h>
+#include <unistd.h>
+#include "cdb++.h"
+#include "internal.h"
+
+#define safeadd(u,v) do{ uint32 newu = u+v; if(newu<u) FAIL; u=newu; }while(0)
+#define FAIL do{ abort(); return false; }while(0)
+
+void cdb_writer::abort()
+{
+  if(!failed) {
+    unlink(fntemp.c_str());
+    out.close();
+    failed = true;
+  }
+}
+
+cdb_writer::cdb_writer(const mystring& filename, int mode)
+  : out(filename.c_str(), fdobuf::excl | fdobuf::create, mode),
+    fntemp(filename),
+    pos(sizeof cdbm.final),
+    failed(false)
+{
+  if(!out)
+    failed = true;
+  else {
+    if(!out.write(cdbm.final, sizeof cdbm.final))
+      abort();
+  }
+}
+
+cdb_writer::~cdb_writer()
+{
+  abort();
+}
+
+bool cdb_writer::put(const mystring& key, const mystring& data)
+{
+  if(failed) return 0;
+  unsigned char packbuf[8];
+  pack(packbuf, key.length());
+  pack(packbuf+4, data.length());
+  if(!out.write(packbuf, sizeof packbuf)) FAIL;
+
+  uint32 h = hash(key);
+  if(!out.write(key.c_str(), key.length()) ||
+     !out.write(data.c_str(), data.length()) ||
+     !cdbm.add(h, pos))
+    FAIL;
+  safeadd(pos, 8);
+  safeadd(pos, key.length());
+  safeadd(pos, data.length());
+  return true;
+}
+
+bool cdb_writer::end(const mystring& filename)
+{
+  if(failed) return 0;
+  if(!cdbm.split_hashes()) FAIL;
+  for(unsigned i = 0; i < 256; i++) {
+    uint32 len = cdbm.throw_hash(pos, i);
+    for(uint32 u = 0; u < len; u++) {
+      unsigned char packbuf[8];
+      pack(packbuf, cdbm.hash[u].h);
+      pack(packbuf+4, cdbm.hash[u].p);
+      if(!out.write(packbuf, sizeof packbuf)) FAIL;
+      safeadd(pos, 8);
+    }
+  }
+  if(!out.rewind()) FAIL;
+  if(!out.write(cdbm.final, sizeof(cdbm.final))) FAIL;
+  if(!out.flush()) FAIL;
+  out.close();
+  if(rename(fntemp.c_str(), filename.c_str())) FAIL;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/cdbtest.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,15 @@
+#include "cdb++.h"
+
+int main()
+{
+  cdb_reader r("cdb.cdb");
+  cdb_writer w("cdb.temp");
+  datum* d;
+  while((d = r.nextrec()) != 0) {
+    datum* t = cdb_getrec("cdb.cdb", d->key);
+    if(t) delete t;
+    w.put(d->key, d->data);
+  }
+  w.end("cdb.cdb");
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/datum.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,32 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "datum.h"
+
+datum::datum(const mystring& k, const mystring& d)
+  : key(k), data(d)
+{
+}
+
+datum::~datum()
+{
+}
+
+fdobuf& operator<<(fdobuf& out, const datum& d)
+{
+  return out << '+' << d.key.length() << ',' << d.data.length()
+	     << ':' << d.key << "->" << d.data;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/datum.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,18 @@
+#ifndef DATUM__H__
+#define DATUM__H__
+
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+
+struct datum 
+{
+  mystring key;
+  mystring data;
+
+  datum(const mystring& k, const mystring& d);
+  ~datum();
+};
+
+fdobuf& operator<<(fdobuf&, const datum&);
+
+#endif // DATUM__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cdb++/internal.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,49 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef CDBXX__INTERNAL__H__
+#define CDBXX__INTERNAL__H__
+
+#include "cdb++.h"
+
+#define CDB_HASHSTART ((uint32) 5381)
+
+inline void pack(unsigned char* buf, uint32 num)
+{
+    *buf++ = num; num >>= 8;
+    *buf++ = num; num >>= 8;
+    *buf++ = num; num >>= 8;
+    *buf = num;
+}
+
+inline uint32 unpack(const unsigned char* p)
+{
+  return uint32(p[0]) |
+    uint32(p[1]) << 8 |
+    uint32(p[2]) << 16 |
+    uint32(p[3]) << 24;
+}
+
+inline uint32 hash(const mystring& s)
+{
+  uint32 h = CDB_HASHSTART;
+  const char* p = s.c_str();
+  for(unsigned len = s.length(); len > 0; len--)
+    h = ((h << 5) + h) ^ *p++;
+  return h;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cgi/ChangeLog	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,8 @@
+1999-09-22  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cgi-args.cc (get): Rewrote the "operator[]" method into a method
+	that could return a default value, and make "operator[]" call get.
+	(get_parts): Modified the code to handle '=' within a part, and
+	parts without any '='.
+	(init): Changed the loop slightly.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cgi/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,8 @@
+noinst_LIBRARIES = libcgi.a
+
+INCLUDES = -I..
+
+libcgi_a_SOURCES = \
+	cgi-args.h cgi-args.cc \
+	cgi-base.h cgi-base.cc
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cgi/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,291 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libcgi.a
+
+INCLUDES = -I..
+
+libcgi_a_SOURCES =  	cgi-args.h cgi-args.cc 	cgi-base.h cgi-base.cc
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libcgi_a_LIBADD = 
+libcgi_a_OBJECTS =  cgi-args.o cgi-base.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  ChangeLog Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libcgi_a_SOURCES)
+OBJECTS = $(libcgi_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/cgi/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libcgi.a: $(libcgi_a_OBJECTS) $(libcgi_a_DEPENDENCIES)
+	-rm -f libcgi.a
+	$(AR) cru libcgi.a $(libcgi_a_OBJECTS) $(libcgi_a_LIBADD)
+	$(RANLIB) libcgi.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/cgi
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+cgi-args.o: cgi-args.cc ../../config.h cgi-args.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../fdbuf/fdbuf.h ../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+cgi-base.o: cgi-base.cc ../../config.h ../ac/time.h cgi-base.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../cgi/cgi-args.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cgi/cgi-args.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,142 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include "cgi-args.h"
+#include "fdbuf/fdbuf.h"
+
+// These routines are optimized for the common case:
+// - few variables (less than ten)
+// - short strings (less than 1K each)
+// - infrequent access relative to the remainder of the code
+
+CGIArgs::~CGIArgs()
+{
+  if(head)
+    delete head;
+}
+
+bool CGIArgs::exists(mystring var) const
+{
+  for(arg* ptr = head; ptr; ptr = ptr->next)
+    if(ptr->var == var)
+      return true;
+  return false;
+}
+
+mystring CGIArgs::get(mystring var, mystring dflt) const
+{
+  for(arg* ptr = head; ptr; ptr = ptr->next)
+    if(ptr->var == var)
+      return ptr->val;
+  return dflt;
+}
+
+void CGIArgs::append(mystring var, mystring val)
+{
+  arg* newarg = new arg(var, val);
+  if(tail)
+    tail->next = newarg;
+  else
+    head = newarg;
+  tail = newarg;
+  ++argc;
+}
+
+static inline int fromhex(char ch)
+{
+  if(ch >= '0' && ch <= '9')
+    return ch - '0';
+  else if(ch >= 'a' && ch <= 'f')
+    return ch - 'a' + 0xa;
+  else if(ch >= 'A' && ch <= 'F')
+    return ch - 'A' + 0xa;
+  else
+    return -1;
+}
+
+static bool get_parts(mystring& var, mystring& val)
+{
+  if(!fin) return false;
+#define BUFSIZE 1024
+  char buf[BUFSIZE];
+  int i = 0;
+  char ch;
+  bool havevar = false;
+  while(fin.get(ch)) {
+    switch(ch) {
+    case '+':
+      buf[i++] = ' ';
+      break;
+    case '%':
+      char ch1, ch2;
+      if(fin.get(ch1) && fin.get(ch2))
+	buf[i++] = fromhex(ch1) << 4 | fromhex(ch2);
+      break;
+    case '=':
+      if(havevar)
+	buf[i++] = ch;
+      else {
+	buf[i] = 0;
+	var += buf;
+	i = 0;
+	havevar = true;
+      }
+      break;
+    case '&':
+      buf[i] = 0;
+      if(havevar)
+	val += buf;
+      else
+	var += buf;
+      return true;
+    default:
+      buf[i++] = ch;
+    }
+    if(i >= BUFSIZE-1) {
+      buf[i] = 0;
+      if(!havevar) var += buf;
+      else val += buf;
+      i = 0;
+    }
+  }
+  if(havevar) {
+    buf[i] = 0;
+    val += buf;
+  }
+  return havevar;
+}
+
+void CGIArgs::init()
+{
+  mystring method = getenv("REQUEST_METHOD");
+  mystring content = getenv("CONTENT_TYPE");
+  if(method != "POST" && method != "post")
+    errstr = "Must be accessed via a CGI 'POST' form";
+  else if(content == "multipart/form-data")
+    errstr = "Must be accessed via a CGI 'POST' form";
+  else {
+    for(;;) {
+      mystring var;
+      mystring val;
+      if(!get_parts(var, val))
+	break;
+      append(var, val);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cgi/cgi-args.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,52 @@
+#ifndef CHECKVPW__CGI_ARGS__H__
+#define CHECKVPW__CGI_ARGS__H__
+
+#include "mystring/mystring.h"
+
+class CGIArgs 
+{
+private:
+  struct arg
+  {
+    arg* next;
+    const mystring var;
+    const mystring val;
+    arg(mystring r, mystring l)
+      : next(0), var(r), val(l)
+      {
+      }
+    ~arg()
+      {
+	delete next;
+      }
+  };
+  arg* head;
+  arg* tail;
+  unsigned argc;
+  mystring errstr;
+protected:
+  void init();
+  void append(mystring, mystring);
+public:
+  CGIArgs() : head(0), tail(0), argc(0)
+    {
+      init();
+    }
+  ~CGIArgs();
+  bool error() const 
+    {
+      return !errstr.empty();
+    }
+  mystring errorstr() const
+    {
+      return errstr;
+    }
+  bool exists(mystring) const;
+  mystring get(mystring var, mystring dflt = 0) const;
+  mystring operator[](mystring var) const
+    {
+      return get(var);
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cgi/cgi-base.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,110 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include "ac/time.h"
+#include <unistd.h>
+#include "cgi-base.h"
+#include "fdbuf/fdbuf.h"
+
+#ifndef HAVE_SRANDOM
+void srandom(unsigned int seed);
+#endif
+
+static void redirect(mystring url)
+{
+  fout << "Location: " << url << "\r\n\r\n";
+}
+
+void content_type(mystring ct)
+{
+  fout << "Content-Type: " << ct << "\r\n\r\n";
+}
+
+static void error_message(mystring msg)
+{
+  content_type("text/html");
+  fout << "<html>"
+    "<head>\n"
+    "<title>CGI Error</title></head>\n"
+    "<body>\n"
+    "<p align=center><h1>CGI Error</h1></p><hr>\n"
+    "<p>The following error occurred while trying to process your request:\r\n"
+    "<pre>\r\n" << msg << "\r\n</pre></p>\r\n";
+  const mystring referer = getenv("HTTP_REFERER");
+  if(!referer.empty())
+    fout << "<p><a href=\"" << referer << "\">Back</a></p>\n";
+  fout << "</body>\n";
+}
+
+static void response_message(mystring msg)
+{
+  content_type("text/html");
+  fout << "<html>"
+    "<head>\n"
+    "<title>CGI Response</title></head>\n"
+    "<body>\n"
+    "<p align=center><h1>CGI Response</h1></p><hr>\n"
+    "<p>" << msg << "</p>\n";
+  const mystring referer = getenv("HTTP_REFERER");
+  if(!referer.empty())
+    fout << "<p><a href=\"" << referer << "\">Back</a></p>\n";
+  fout << "</body>\n";
+}
+
+CGI::CGI(const CGIArgs& a)
+  : args(a),
+    redirect_url(a["redirect"]),
+    error_redirect_url(a["error_redirect"]),
+    vdomain(a["vdomain"]),
+    password(a["password"])
+{
+  must_be_defined("vdomain");
+  must_be_defined("password");
+}
+
+void CGI::must_be_defined(mystring var)
+{
+  if(!args.exists(var))
+    error("The input field '" + var + "' must be defined");
+}
+
+void CGI::success(mystring msg)
+{
+  if(!redirect_url) response_message(msg);
+  else redirect(redirect_url);
+  exit(0);
+}
+
+void CGI::error(mystring msg)
+{
+  if(!error_redirect_url) error_message(msg);
+  else redirect(error_redirect_url);
+  exit(1);
+}
+
+int main(void)
+{
+  struct timeval tv;
+  gettimeofday(&tv, 0);
+  srandom(tv.tv_usec ^ tv.tv_sec);
+  CGIArgs cgiargs;
+  if(cgiargs.error())
+    error_message(cgiargs.errorstr());
+  else
+    CGI(cgiargs).main();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cgi/cgi-base.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,39 @@
+#ifndef CHECKVPW__CGI_BASE__H__
+#define CHECKVPW__CGI_BASE__H__
+
+#include "mystring/mystring.h"
+#include "cgi/cgi-args.h"
+
+extern void content_type(mystring ct);
+
+class CGI
+{
+protected:
+  const CGIArgs& args;
+
+  const mystring redirect_url, error_redirect_url;
+  const mystring vdomain, password;
+  
+  void error(mystring);
+  void success(mystring);
+
+  void must_be_defined(mystring);
+  
+public:
+  CGI(const CGIArgs& a);
+  
+  void main();
+};
+
+#define CGI_MAIN void CGI::main()
+
+#define CGI_INPUT(VAR) \
+  const mystring VAR##__name__ = #VAR; \
+  must_be_defined(VAR##__name__); \
+  mystring VAR = args[VAR##__name__];
+
+#define CGI_OPTINPUT(VAR) \
+  const mystring VAR##__name__ = #VAR; \
+  mystring VAR = args[VAR##__name__];
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/ChangeLog	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,115 @@
+2000-08-15  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* cli2pod.pl: Replaced the CLI documentation programs with this
+	script which outputs POD, which can be translated to man pages or
+	HTML (or LaTeX, or text, or FM).
+
+2000-08-14  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* cli_parse.pl (parse_header_line): Rewrote the parsing to deal
+	with multi-line strings.
+
+	* cli2man.pl (synopsis): Add usage string.
+
+	* cli2html.pl (synopsis): Add usage string.
+
+2000-08-12  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* cli_parse.pl, cli2html.pl, cli2man.pl: Created these programs.
+
+2000-08-01  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* main.cc (show_option): Fixed several width glitches.
+
+2000-07-18  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* cli.h (struct cli_option): Added new uinteger type.
+
+	* main.cc (fill): Removed use of mystring.
+
+2000-07-13  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* Removed include of mystring.
+
+2000-01-09  Bruce Guenter  <bruceg@daedalus.bfsmedia.com>
+
+	* main.cc (parse_short): Modified the logic here to treat a string
+	value immediately following a string option as the value for that
+	option rather than as more flags.  This makes it behave much more
+	like the standard getopt library.
+
+1999-09-30  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc (show_option): Changed stringlist option string from
+	"=LIST" to "=ITEM".
+
+1999-09-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc (cli_option::set): Fixed problem with setting a string
+	list option.
+
+1999-09-11  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc (show_help): Split off two parts of this routine into
+	calc_max_width and show_option.
+	(show_option): Add "=INT" for integer options, and don't add extra
+	space for non-value long options.
+	(set): Use strtol instead of atoi to parse the integer string, to
+	allow for error checking.
+	(show_option): Fixed handling of string lists.
+
+1999-08-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc (set_argv0): Sets argv0 to the complete value of
+	argv[0], argv0dir to the part of argv[0] up to and including the
+	last '/' (or blank if there is none), and argv0base to the
+	remainder of argv[0].  This is for use in programs that determine
+	what to do based on the value of the program name.
+
+1999-07-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc (parse_long_eq): Fixed to account for "counter" flag
+	type.
+	(parse_long_noeq): Fixed to account for "counter" flag type.
+	(parse_long_eq): set() will return one, but this shouldn't return
+	one, so subtract one from its result.
+	(show_help): Added a mechanism to display default values on a
+	second line.
+	(show_help): Output a blank line before the "--help" option line.
+
+1999-07-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc (show_help): Only show a "=VALUE" for string and integer
+	option types.
+
+1999-06-30  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* messages.cc (cli_error): Moved this routine into a separate
+	module, and added a "cli_warning" routine.
+
+1999-06-25  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc (set): Added handling for two new option types: string
+	list and counters.  A stringlist maintains a linked list of all
+	the given option arguments.  A counter adds the flag_value to the
+	dataptr each time it is encountered.
+	(parse_short): Fixed faulty logic regarding options with values.
+	Need to merge parts into cli_option::set().
+
+1999-06-24  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* main.cc: Rewrote the "help" option handling to stop it being a
+	special case, by making an internal option list that includes a
+	"help" option at the end of it.
+	(show_help): Cleaned up the option formatting to produce more
+	correct output.
+	(build_options): Removed the need to count the options.  Note
+	that this breaks compatibility with previous versions.
+	(cli_error): Added this convenience function for the CLI program
+	to report errors and optionally exit.
+	(set): Added functionality to call functions when an option is
+	parsed, and moved some of the option parsing into class methods
+	from the structure.
+	(main): Moved the test for showing the usage information before
+	the test for counting command-line arguments.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libcli.a
+EXTRA_DIST = clitest.cc cli2pod.pl
+
+INCLUDES = -I..
+#LIBS = @LIBS@ -L. -lcli -L../lib -lvmailmgr
+
+libcli_a_SOURCES = cli.h main.cc messages.cc
+#clitest_SOURCES = clitest.cc
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,290 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libcli.a
+EXTRA_DIST = clitest.cc cli2pod.pl
+
+INCLUDES = -I..
+#LIBS = @LIBS@ -L. -lcli -L../lib -lvmailmgr
+
+libcli_a_SOURCES = cli.h main.cc messages.cc
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libcli_a_LIBADD = 
+libcli_a_OBJECTS =  main.o messages.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  ChangeLog Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libcli_a_SOURCES)
+OBJECTS = $(libcli_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/cli/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libcli.a: $(libcli_a_OBJECTS) $(libcli_a_DEPENDENCIES)
+	-rm -f libcli.a
+	$(AR) cru libcli.a $(libcli_a_OBJECTS) $(libcli_a_LIBADD)
+	$(RANLIB) libcli.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/cli
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+main.o: main.cc ../../config.h ../ac/time.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h cli.h
+messages.o: messages.cc ../../config.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h cli.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+#clitest_SOURCES = clitest.cc
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/cli.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,59 @@
+#ifndef VMAILMGR__CLI__CLI__H__
+#define VMAILMGR__CLI__CLI__H__
+
+typedef bool (*cli_funcptr)(void*);
+
+struct cli_stringlist
+{
+  const char* string;
+  cli_stringlist* next;
+
+  cli_stringlist(const char* s)
+    : string(s), next(0)
+    {
+    }
+};
+
+struct cli_option
+{
+  char ch;
+  const char* name;
+  enum { flag, counter, integer, string, stringlist, uinteger } type;
+  int flag_value;
+  void* dataptr;
+  const char* helpstr;
+  const char* defaultstr;
+
+  int set(const char* arg);
+  int parse_long_eq(const char* arg);
+  int parse_long_noeq(const char* arg);
+};
+
+/* The following are required from the CLI program */
+extern const char* cli_program;
+extern const char* cli_help_prefix;
+extern const char* cli_help_suffix;
+extern const char* cli_args_usage;
+extern const int cli_args_min;
+extern const int cli_args_max;
+extern cli_option cli_options[];
+extern int cli_main(int argc, char* argv[]);
+
+/* The following are provided to the CLI program */
+extern const char* argv0;
+extern const char* argv0base;
+extern const char* argv0dir;
+extern void usage(int exit_value, const char* errorstr = 0);
+
+extern void cli_error(int exit_value,
+		      const char*,
+		      const char* = 0,
+		      const char* = 0,
+		      const char* = 0);
+
+extern void cli_warning(const char*,
+		      const char* = 0,
+		      const char* = 0,
+		      const char* = 0);
+
+#endif // VMAILMGR__CLI__CLI__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/cli2pod.pl	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,212 @@
+#!/usr/bin/perl
+
+sub cstr2pod {
+    local($_) = shift;
+    s/\\"/"/go;
+    s/"([^\"]*)"/"C<$1>"/go;
+    $_;
+}
+
+$section = 1;
+
+@section_order = (
+		  'NAME',
+		  'SYNOPSIS',
+		  'DESCRIPTION',
+		  'OPTIONS',
+		  'RETURN VALUE',
+		  'ERRORS',
+		  'EXAMPLES',
+		  'ENVIRONMENT',
+		  'FILES',
+		  'SEE ALSO',
+		  'NOTES',
+		  'CAVEATS',
+		  'WARNINGS',
+		  'DIAGNOSTICS',
+		  'BUGS',
+		  'RESTRICTIONS',
+		  'AUTHOR',
+		  'AUTHORS',
+		  'HISTORY'
+		  );
+
+sub type2word {
+    my($type) = shift;
+    return 'INT' if $type eq 'integer';
+    return 'UINT' if $type eq 'uinteger';
+    return 'STR' if $type eq 'string' || $type eq 'stringlist';
+    return '' if $type eq 'flag' || $type eq 'counter';
+    die "Invalid cli option type '$type'";
+}
+
+sub add_option {
+    my($short, $long, $type, $desc) = @_;
+
+    my $s = '[B<';
+    my $o = '=item B<';
+    if($short) {
+	$s .= "-$short";
+	$o .= "-$short";
+	if($type) {
+	    $s .= " $type";
+	    $o .= " $type";
+	}
+    }
+    if($short && $long) {
+	$s .= ">]\n[B<";
+	$o .= ">, B<";
+    }
+    if($long) {
+	$s .= "--$long";
+	$o .= "--$long";
+	if($type) {
+	    $s .= "=$type";
+	    $o .= "=$type";
+	}
+    }
+    $s .= ">]\n";
+    $o .= ">\n\n$desc\n\n";
+
+    $synopsis .= $s;
+    $options = "=over 8\n\n" unless $options;
+    $options .= $o;
+}
+
+sub parse_option {
+    local($_) = shift;
+    s/^\s*\{\s*//o;
+    s/\s*\},?\s*/ /o;
+
+    my $short = $1 if s/^'([^\'])',\s*//o;
+    die "Invalid cli option" unless $short || s/^0,\s*//o;
+
+    my $long = $1 if s/^"([^\"]+)",\s*//o;
+    die "Invalid cli_option" unless $long || s/^0,\s*//o;
+
+    my $type = $1 if s/^cli_option::(\S+),\s*//o;
+    die "Invalid cli_option" unless $type;
+    $type = &type2word($type);
+
+    my $val = $1 if s/^([^,]+),\s*//o;
+    my $var = $1 if s/^&([^,]+),\s*//o;
+
+    my $desc = cstr2pod($1) if s/^"([^,]+)",\s*//o;
+    die "Invalid cli_option" unless $desc;
+    $desc =~ s/\.?$/./o if $desc;
+
+    my $default = $1 if s/^"([^\"]+)"\s+//o;
+    die "Invalid cli_option" unless $default || s/^0\s+//o;
+    $desc .= " Defaults to $default." if $default;
+
+    s/\s*\/\/\s*/ /go;
+    s/^\s*//o;
+
+    add_option($short, $long, $type, $_ || $desc);
+}
+
+sub parse_options {
+    $synopsis = "B<$program>\n";
+
+    my $line;
+    while(<>) {
+	s/^\s+//o;
+	s/\s+$//o;
+	if($line && /^\{/o) {
+	    &parse_option($line);
+	    $line = "";
+	}
+	next if /^\{\s*0\s*\},?/o;
+	last if /^\s*\};/o;
+	$line =~ s/$/ $_/;
+    }
+    &parse_option($line) if $line;
+
+    $synopsis .= "I<$usage>" if $usage;
+    $options .= "=back" if $options;
+    $sections{'SYNOPSIS'} = $synopsis;
+    $sections{'OPTIONS'} = $options;
+}
+
+sub parse_notes {
+    my $section;
+    my $title;
+    while(<>) {
+	chomp;
+	last unless /^$/o || s/^\/\/\s*//o;
+	if(/^[\sA-Z]+$/o) {
+	    $sections{$title} = $section if $title && $section;
+	    undef $section;
+	    $title = $_;
+	} else {
+	    $section .= "$_\n";
+	}
+    }
+    $sections{$title} = $section if $title && $section;
+}
+
+sub parse_header_line {
+    local($_, $comment) = @_;
+    if(s/^\s*const\s+char\s*\*\s*cli_(\S+)\s*=\s*//o) {
+	my $name = $1;
+	s/;\s*$//o;
+	s/^\"//;
+	s/\"$//o;
+	s/\\n$//o;
+	s/\\n""/\n/go;
+	$program = $_ if $name eq 'program';
+	$prefix = $_ if $name eq 'help_prefix';
+	$usage = $_ if $name eq 'args_usage';
+	$suffix = $_ if $name eq 'help_suffix';
+    }
+}
+
+sub parse_header {
+    my $comment = '';
+    my $line = '';
+    while(<>) {
+	s/^\s+//o;
+	s/\s+$//o;
+	if(s/^.*Copyright\s*\(C\)\s*[\d,]+\s*//o) {
+	    $author = $_;
+	} else {
+	    last if ($program && $prefix && /^$/o);
+	    next if /^#/o;
+	    $comment .= "$1\n" if s|\s*//\s*(.*)$||o;
+	    $line =~ s/$/\n$_/;
+	    if(/;$/o) {
+		&parse_header_line($line, $comment);
+		undef $line;
+		undef $comment;
+	    }
+	}
+    }
+}
+
+sub parse_description {
+    while(<>) {
+	s/^\s+//o;
+	s/\s+$//o;
+	last if / cli_options\[\]\s*=\s*\{/o;
+	next unless s/^\/\/\s*//o;
+	$description .= "$_\n";
+    }
+}
+
+&parse_header;
+&parse_description;
+&parse_options;
+&parse_notes;
+
+$description .= "\n\n$suffix\n" if $suffix;
+
+$sections{'NAME'} = "$program - $prefix";
+$sections{'DESCRIPTION'} = $description;
+$sections{'AUTHORS'} = $author if $author;
+
+foreach $section (@section_order) {
+    print "=head1 $section\n\n$sections{$section}\n\n"
+	if $sections{$section};
+}
+
+1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/clitest.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,47 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "cli.h"
+#include "fdbuf/fdbuf.h"
+
+const char* cli_program = "clitest";
+const char* cli_help_prefix = "Does nothing but set flags\n";
+const char* cli_help_suffix = "";
+const char* cli_args_usage = "";
+const int cli_args_min = 0;
+const int cli_args_max = -1;
+int o_flag = 0;
+int o_int = 0;
+char* o_string = "nostring";
+cli_option cli_options[] = { 
+  { 'f', "flag", cli_option::flag, 1, &o_flag, "Sets a flag", 0 },
+  { 'i', "int", cli_option::integer, 0, &o_int, "Sets an integer", 0 },
+  { 's', "str", cli_option::string, 0, &o_string, "Sets a string", 0},
+  {0} };
+
+int cli_main(int argc, char* argv[])
+{
+  fout << "argv0=" << argv0 << endl
+       << " argv0dir=" << argv0dir << endl
+       << " argv0base=" << argv0base << endl;
+  fout << "The flag is set to " << o_flag << endl;
+  fout << "The integer is set to " << o_int << endl;
+  fout << "The string is set to " << o_string << endl;
+  for(int i = 0; i < argc; i++)
+    fout << "argv[" << i << "] = '" << argv[i] << "'\n";
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/main.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,342 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "ac/time.h"
+#include "fdbuf/fdbuf.h"
+#include <stdlib.h>
+#include <string.h>
+#include "cli.h"
+
+#ifndef HAVE_SRANDOM
+void srandom(unsigned int seed);
+#endif
+
+static bool do_show_usage = false;
+const char* argv0;
+const char* argv0base;
+const char* argv0dir;
+
+static cli_option help_option = { 'h', "help", cli_option::flag,
+				  true, &do_show_usage,
+				  "Display this help and exit", 0 };
+
+static cli_option** options;
+static unsigned optionc;
+
+static void build_options()
+{
+  for(optionc = 0;
+      cli_options[optionc].ch || cli_options[optionc].name;
+      optionc++) ;
+  optionc++;
+  options = new cli_option*[optionc];
+  for(unsigned i = 0; i < optionc-1; i++)
+    options[i] = &cli_options[i];
+  options[optionc-1] = &help_option;
+}
+
+static inline unsigned max(unsigned a, unsigned b)
+{
+  return (a>b) ? a : b;
+}
+
+static const char* fill(unsigned i)
+{
+  static unsigned lastlen = 0;
+  static char* buf = 0;
+  if(i > lastlen) {
+    delete[] buf;
+    buf = new char[i+1];
+    lastlen = i;
+  }
+  memset(buf, ' ', i);
+  buf[i] = 0;
+  return buf;
+}
+  
+static void show_usage()
+{
+  fout << "usage: " << cli_program << " [flags] " << cli_args_usage << endl;
+}
+
+static unsigned calc_max_width()
+{
+  // maxwidth is the maximum width of the long argument
+  unsigned maxwidth = 0;
+  for(unsigned i = 0; i < optionc; i++) {
+    unsigned width = 0;
+    cli_option* o = options[i];
+    if(o->name) {
+      width += strlen(o->name);
+      switch(o->type) {
+      case cli_option::string:     width += 6; break;
+      case cli_option::integer:    width += 4; break;
+      case cli_option::uinteger:   width += 4; break;
+      case cli_option::stringlist: width += 5; break;
+      case cli_option::flag:       break;
+      case cli_option::counter:    break;
+      }
+    }
+    if(width > maxwidth)
+      maxwidth = width;
+  }
+  return maxwidth;
+}
+
+static void show_option(cli_option* o, unsigned maxwidth)
+{
+  if(o == &help_option)
+    fout << '\n';
+  if(o->ch)
+    fout << "  -" << o->ch;
+  else
+    fout << "    ";
+  fout << (o->ch && o->name ? ", " : "  ");
+  if(o->name) {
+    const char* extra = "";
+    switch(o->type) {
+    case cli_option::string:     extra = "=VALUE"; break;
+    case cli_option::integer:    extra = "=INT"; break;
+    case cli_option::uinteger:   extra = "=UNS"; break;
+    case cli_option::stringlist: extra = "=ITEM"; break;
+    case cli_option::flag:       break;
+    case cli_option::counter:    break;
+    }
+    fout << "--" << o->name << extra
+	 << fill(maxwidth - strlen(o->name) - strlen(extra) + 2);
+  }
+  else
+    fout << fill(maxwidth+4);
+  fout << o->helpstr << '\n';
+  if(o->defaultstr)
+    fout << fill(maxwidth+10) << "(Defaults to " << o->defaultstr << ")\n";
+}
+
+static void show_help()
+{
+  if(cli_help_prefix)
+    fout << cli_help_prefix;
+  unsigned maxwidth = calc_max_width();
+  for(unsigned i = 0; i < optionc; i++)
+    show_option(options[i], maxwidth);
+  if(cli_help_suffix)
+    fout << cli_help_suffix;
+}
+
+void usage(int exit_value, const char* errorstr)
+{
+  if(errorstr)
+    ferr << cli_program << ": " << errorstr << endl;
+  show_usage();
+  show_help();
+  exit(exit_value);
+}
+
+cli_stringlist* stringlist_append(cli_stringlist* node, const char* newstr)
+{
+  cli_stringlist* newnode = new cli_stringlist(newstr);
+  if(node) {
+    cli_stringlist* head = node;
+    while(node->next)
+      node = node->next;
+    node->next = newnode;
+    return head;
+  }
+  else
+    return newnode;
+}
+
+int cli_option::set(const char* arg)
+{
+  char* endptr;
+  switch(type) {
+  case flag:
+    *(int*)dataptr = flag_value;
+    return 0;
+  case counter:
+    *(int*)dataptr += flag_value;
+    return 0;
+  case integer:
+    *(int*)dataptr = strtol(arg, &endptr, 10);
+    if(*endptr) {
+      ferr << argv0 << ": invalid integer: " << arg << endl;
+      return -1;
+    }
+    return 1;
+  case uinteger:
+    *(unsigned*)dataptr = strtoul(arg, &endptr, 10);
+    if(*endptr) {
+      ferr << argv0 << ": invalid unsigned integer: " << arg << endl;
+      return -1;
+    }
+    return 1;
+  case stringlist:
+    *(cli_stringlist**)dataptr =
+      stringlist_append(*(cli_stringlist**)dataptr, arg);
+    return 1;
+  default: // string
+    *(const char**)dataptr = arg;
+    return 1;
+  }
+}
+
+static int parse_short(int argc, char* argv[])
+{
+  int end = strlen(argv[0]) - 1;
+  for(int i = 1; i <= end; i++) {
+    int ch = argv[0][i];
+    unsigned j;
+    for(j = 0; j < optionc; j++) {
+      cli_option* o = options[j];
+      if(o->ch == ch) {
+	if(o->type != cli_option::flag &&
+	   o->type != cli_option::counter) {
+	  if(i < end) {
+	    if(o->set(argv[0]+i+1) != -1)
+	      return 0;
+	  }
+	  else if(argc <= 1) {
+	    ferr << argv0 << ": option -" << o->ch
+		 << " requires a value." << endl;
+	  }
+	  else
+	    if(o->set(argv[1]) != -1)
+	      return 1;
+	}
+	else if(o->set(0) != -1)
+	  break;
+	return -1;
+      }
+    }
+    if(j >= optionc) {
+      ferr << argv0 << ": unknown option letter -" << argv[0][i] << endl;
+      return -1;
+    }
+  }
+  return 0;
+}
+
+int cli_option::parse_long_eq(const char* arg)
+{
+  if(type == flag || type == counter) {
+    ferr << argv0 << ": option --" << name
+	 << " does not take a value." << endl;
+    return -1;
+  }
+  else
+    return set(arg)-1;
+}
+
+int cli_option::parse_long_noeq(const char* arg)
+{
+  if(type == flag || type == counter)
+    return set(0);
+  else if(arg)
+    return set(arg);
+  else {
+    ferr << argv0 << ": option --" << name
+	 << " requires a value." << endl;
+    return -1;
+  }
+}
+
+static int parse_long(int, char* argv[])
+{
+  const char* arg = argv[0]+2;
+  for(unsigned j = 0; j < optionc; j++) {
+    cli_option* o = options[j];
+    if(o->name) {
+      size_t len = strlen(o->name);
+      if(!memcmp(arg, o->name, len)) {
+	if(arg[len] == '\0')
+	  return o->parse_long_noeq(argv[1]);
+	else if(arg[len] == '=')
+	  return o->parse_long_eq(arg+len+1);
+      }
+    }
+  }
+  ferr << argv0 << ": unknown option string: '--" << arg << "'" << endl;
+  return -1;
+}
+
+static int parse_args(int argc, char* argv[])
+{
+  build_options();
+  int i;
+  for(i = 1; i < argc; i++) {
+    const char* arg = argv[i];
+    // Stop at the first non-option argument
+    if(arg[0] != '-')
+      break;
+    // Stop after the first "-" or "--"
+    if(arg[1] == '\0' ||
+       (arg[1] == '-' && arg[2] == '\0')) {
+      i++;
+      break;
+    }
+    int j = (arg[1] != '-') ?
+      parse_short(argc-i, argv+i) :
+      parse_long(argc-i, argv+i);
+    if(j < 0)
+      usage(1);
+    else
+      i += j;
+  }
+  return i;
+}
+
+static void set_argv0(const char* p)
+{
+  argv0 = p;
+  static const char* empty = "";
+  const char* s = strrchr(p, '/');
+  if(s) {
+    ++s;
+    argv0base = s;
+    size_t length = s-p;
+    char* tmp = new char[length+1];
+    memcpy(tmp, p, length);
+    tmp[length] = 0;
+    argv0dir = tmp;
+  }
+  else {
+    argv0base = p;
+    argv0dir = empty;
+  }
+}
+
+int main(int argc, char* argv[])
+{
+  struct timeval tv;
+  gettimeofday(&tv, 0);
+  srandom(tv.tv_usec ^ tv.tv_sec);
+  
+  set_argv0(argv[0]);
+  int lastarg = parse_args(argc, argv);
+
+  if(do_show_usage)
+    usage(0);
+
+  argc -= lastarg;
+  argv += lastarg;
+  if(argc < cli_args_min)
+    usage(1, "Too few command-line arguments");
+  if(cli_args_max >= cli_args_min && argc > cli_args_max)
+    usage(1, "Too many command-line arguments");
+  
+  return cli_main(argc, argv);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cli/messages.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,44 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "fdbuf/fdbuf.h"
+#include <stdlib.h>
+#include "cli.h"
+
+extern const char* argv0;
+
+void cli_error(int exit_value,
+	       const char* a,
+	       const char* b,
+	       const char* c,
+	       const char* d)
+{
+  cli_warning(a,b,c,d);
+  exit(exit_value);
+}
+
+void cli_warning(const char* a,
+	       const char* b,
+	       const char* c,
+	       const char* d)
+{
+  ferr << cli_program << ": " << a;
+  if(b) ferr << b;
+  if(c) ferr << c;
+  if(d) ferr << d;
+  ferr << endl;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,38 @@
+noinst_LIBRARIES = libconfig.a
+bin_PROGRAMS = showvconfig
+EXTRA_DIST = configrc.in build-config.sh \
+	configrc.h.in Makefile.am.in configvar.in showvconfig.cc.in
+
+INCLUDES = -I..
+
+libconfig_a_SOURCES = \
+	_autoresponse_dir.cc \
+	_autoresponse_file.cc \
+	_bulletin_dir.cc \
+	_default_expiry.cc \
+	_default_maildir.cc \
+	_default_msgcount.cc \
+	_default_msgsize.cc \
+	_default_hardquota.cc \
+	_default_softquota.cc \
+	_default_username.cc \
+	_error_maildir.cc \
+	_global_bulletin_dir.cc \
+	_maildir_arg_str.cc \
+	_password_file.cc \
+	_postmaster_aliases.cc \
+	_postmaster_email.cc \
+	_qmail_root.cc \
+	_separators.cc \
+	_socket_file.cc \
+	_user_dir.cc \
+	_user_dir_bits.cc \
+	_user_dir_slices.cc \
+	configio.h config_read.cc \
+	configrc.h configrc.cc \
+	read_dir.cc read_list.cc read_str.cc read_uns.cc
+
+showvconfig_SOURCES = showvconfig.cc
+showvconfig_LDADD = libconfig.a ../fdbuf/libfdbuf.a ../misc/libmisc.a \
+	../mystring/libmystring.a ../vdomain/libvdomain.a \
+	../vpwtable/libvpwtable.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/Makefile.am.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,17 @@
+noinst_LIBRARIES = libconfig.a
+bin_PROGRAMS = showvconfig
+EXTRA_DIST = configrc.in build-config.sh \
+	configrc.h.in Makefile.am.in configvar.in showvconfig.cc.in
+
+INCLUDES = -I..
+
+libconfig_a_SOURCES = \
+%%LIST%%
+	configio.h config_read.cc \
+	configrc.h configrc.cc \
+	read_dir.cc read_list.cc read_str.cc read_uns.cc
+
+showvconfig_SOURCES = showvconfig.cc
+showvconfig_LDADD = libconfig.a ../fdbuf/libfdbuf.a ../misc/libmisc.a \
+	../mystring/libmystring.a ../vdomain/libvdomain.a \
+	../vpwtable/libvpwtable.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,436 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libconfig.a
+bin_PROGRAMS = showvconfig
+EXTRA_DIST = configrc.in build-config.sh 	configrc.h.in Makefile.am.in configvar.in showvconfig.cc.in
+
+
+INCLUDES = -I..
+
+libconfig_a_SOURCES =  	_autoresponse_dir.cc 	_autoresponse_file.cc 	_bulletin_dir.cc 	_default_expiry.cc 	_default_maildir.cc 	_default_msgcount.cc 	_default_msgsize.cc 	_default_hardquota.cc 	_default_softquota.cc 	_default_username.cc 	_error_maildir.cc 	_global_bulletin_dir.cc 	_maildir_arg_str.cc 	_password_file.cc 	_postmaster_aliases.cc 	_postmaster_email.cc 	_qmail_root.cc 	_separators.cc 	_socket_file.cc 	_user_dir.cc 	_user_dir_bits.cc 	_user_dir_slices.cc 	configio.h config_read.cc 	configrc.h configrc.cc 	read_dir.cc read_list.cc read_str.cc read_uns.cc
+
+
+showvconfig_SOURCES = showvconfig.cc
+showvconfig_LDADD = libconfig.a ../fdbuf/libfdbuf.a ../misc/libmisc.a 	../mystring/libmystring.a ../vdomain/libvdomain.a 	../vpwtable/libvpwtable.a
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libconfig_a_LIBADD = 
+libconfig_a_OBJECTS =  _autoresponse_dir.o _autoresponse_file.o \
+_bulletin_dir.o _default_expiry.o _default_maildir.o \
+_default_msgcount.o _default_msgsize.o _default_hardquota.o \
+_default_softquota.o _default_username.o _error_maildir.o \
+_global_bulletin_dir.o _maildir_arg_str.o _password_file.o \
+_postmaster_aliases.o _postmaster_email.o _qmail_root.o _separators.o \
+_socket_file.o _user_dir.o _user_dir_bits.o _user_dir_slices.o \
+config_read.o configrc.o read_dir.o read_list.o read_str.o read_uns.o
+AR = ar
+PROGRAMS =  $(bin_PROGRAMS)
+
+showvconfig_OBJECTS =  showvconfig.o
+showvconfig_DEPENDENCIES =  libconfig.a ../fdbuf/libfdbuf.a \
+../misc/libmisc.a ../mystring/libmystring.a ../vdomain/libvdomain.a \
+../vpwtable/libvpwtable.a
+showvconfig_LDFLAGS = 
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libconfig_a_SOURCES) $(showvconfig_SOURCES)
+OBJECTS = $(libconfig_a_OBJECTS) $(showvconfig_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/config/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libconfig.a: $(libconfig_a_OBJECTS) $(libconfig_a_DEPENDENCIES)
+	-rm -f libconfig.a
+	$(AR) cru libconfig.a $(libconfig_a_OBJECTS) $(libconfig_a_LIBADD)
+	$(RANLIB) libconfig.a
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "  $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	     $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+showvconfig: $(showvconfig_OBJECTS) $(showvconfig_DEPENDENCIES)
+	@rm -f showvconfig
+	$(CXXLINK) $(showvconfig_LDFLAGS) $(showvconfig_OBJECTS) $(showvconfig_LDADD) $(LIBS)
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/config
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+_autoresponse_dir.o: _autoresponse_dir.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_autoresponse_file.o: _autoresponse_file.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_bulletin_dir.o: _bulletin_dir.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_default_expiry.o: _default_expiry.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_default_hardquota.o: _default_hardquota.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_default_maildir.o: _default_maildir.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_default_msgcount.o: _default_msgcount.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_default_msgsize.o: _default_msgsize.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_default_softquota.o: _default_softquota.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_default_username.o: _default_username.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_error_maildir.o: _error_maildir.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_global_bulletin_dir.o: _global_bulletin_dir.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_maildir_arg_str.o: _maildir_arg_str.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_max_fork.o: _max_fork.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_password_file.o: _password_file.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_postmaster_aliases.o: _postmaster_aliases.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_postmaster_email.o: _postmaster_email.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+_qmail_root.o: _qmail_root.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_separators.o: _separators.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_socket_file.o: _socket_file.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_user_dir.o: _user_dir.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_user_dir_bits.o: _user_dir_bits.cc configio.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h
+_user_dir_slices.o: _user_dir_slices.cc configio.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h
+config_read.o: config_read.cc ../../config.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../fdbuf/fdbuf.h ../fdbuf/fdibuf.h ../fdbuf/fdobuf.h configio.h \
+	../config/configrc.h ../misc/strlist.h
+configrc.o: configrc.cc ../../config.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../fdbuf/fdbuf.h ../fdbuf/fdibuf.h ../fdbuf/fdobuf.h configrc.h \
+	../misc/strlist.h
+read_dir.o: read_dir.cc ../../config.h configrc.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h configio.h ../config/configrc.h
+read_list.o: read_list.cc ../../config.h configrc.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h
+read_str.o: read_str.cc ../../config.h configrc.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h configio.h ../config/configrc.h
+read_uns.o: read_uns.cc ../../config.h configrc.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h configio.h ../config/configrc.h \
+	../misc/strtou.h
+showvconfig.o: showvconfig.cc ../../config.h ../misc/pwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h \
+	../vdomain/vdomain.h ../vpwtable/vpwtable.h \
+	../vpwentry/vpwentry.h ../misc/response.h configrc.h \
+	../fdbuf/fdbuf.h ../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(bindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-binPROGRAMS mostlyclean-tags \
+		mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-binPROGRAMS \
+		clean-tags clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-binPROGRAMS distclean-tags distclean-generic \
+		clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-binPROGRAMS \
+		maintainer-clean-tags maintainer-clean-generic \
+		distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-binPROGRAMS distclean-binPROGRAMS \
+clean-binPROGRAMS maintainer-clean-binPROGRAMS uninstall-binPROGRAMS \
+install-binPROGRAMS tags mostlyclean-tags distclean-tags clean-tags \
+maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_autoresponse_dir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_autoresponse_dir("autoresponse");
+static const mystring filename_autoresponse_dir = "autoresponse-dir";
+mystring configuration::autoresponse_dir() const {
+  return read_dir(filename_autoresponse_dir,
+                    default_autoresponse_dir,
+		    (config_cache<mystring>&)autoresponse_dir_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_autoresponse_file.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_autoresponse_file("message.txt");
+static const mystring filename_autoresponse_file = "autoresponse-file";
+mystring configuration::autoresponse_file() const {
+  return read_str(filename_autoresponse_file,
+                    default_autoresponse_file,
+		    (config_cache<mystring>&)autoresponse_file_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_bulletin_dir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_bulletin_dir("bulletins");
+static const mystring filename_bulletin_dir = "bulletin-dir";
+mystring configuration::bulletin_dir() const {
+  return read_dir(filename_bulletin_dir,
+                    default_bulletin_dir,
+		    (config_cache<mystring>&)bulletin_dir_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_default_expiry.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static unsigned default_default_expiry(UINT_MAX);
+static const mystring filename_default_expiry = "default-expiry";
+unsigned configuration::default_expiry() const {
+  return read_uns(filename_default_expiry,
+                    default_default_expiry,
+		    (config_cache<unsigned>&)default_expiry_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_default_hardquota.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static unsigned default_default_hardquota(UINT_MAX);
+static const mystring filename_default_hardquota = "default-hardquota";
+unsigned configuration::default_hardquota() const {
+  return read_uns(filename_default_hardquota,
+                    default_default_hardquota,
+		    (config_cache<unsigned>&)default_hardquota_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_default_maildir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_default_maildir("Maildir");
+static const mystring filename_default_maildir = "default-maildir";
+mystring configuration::default_maildir() const {
+  return read_dir(filename_default_maildir,
+                    default_default_maildir,
+		    (config_cache<mystring>&)default_maildir_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_default_msgcount.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static unsigned default_default_msgcount(UINT_MAX);
+static const mystring filename_default_msgcount = "default-msgcount";
+unsigned configuration::default_msgcount() const {
+  return read_uns(filename_default_msgcount,
+                    default_default_msgcount,
+		    (config_cache<unsigned>&)default_msgcount_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_default_msgsize.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static unsigned default_default_msgsize(UINT_MAX);
+static const mystring filename_default_msgsize = "default-msgsize";
+unsigned configuration::default_msgsize() const {
+  return read_uns(filename_default_msgsize,
+                    default_default_msgsize,
+		    (config_cache<unsigned>&)default_msgsize_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_default_softquota.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static unsigned default_default_softquota(UINT_MAX);
+static const mystring filename_default_softquota = "default-softquota";
+unsigned configuration::default_softquota() const {
+  return read_uns(filename_default_softquota,
+                    default_default_softquota,
+		    (config_cache<unsigned>&)default_softquota_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_default_username.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_default_username("+");
+static const mystring filename_default_username = "default-username";
+mystring configuration::default_username() const {
+  return read_str(filename_default_username,
+                    default_default_username,
+		    (config_cache<mystring>&)default_username_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_error_maildir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_error_maildir("/var/lib/vmailmgr/error-maildir");
+static const mystring filename_error_maildir = "error-maildir";
+mystring configuration::error_maildir() const {
+  return read_dir(filename_error_maildir,
+                    default_error_maildir,
+		    (config_cache<mystring>&)error_maildir_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_global_bulletin_dir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_global_bulletin_dir("/var/spool/bulletins");
+static const mystring filename_global_bulletin_dir = "global-bulletin-dir";
+mystring configuration::global_bulletin_dir() const {
+  return read_dir(filename_global_bulletin_dir,
+                    default_global_bulletin_dir,
+		    (config_cache<mystring>&)global_bulletin_dir_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_maildir_arg_str.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_maildir_arg_str("maildir");
+static const mystring filename_maildir_arg_str = "maildir-arg-str";
+mystring configuration::maildir_arg_str() const {
+  return read_str(filename_maildir_arg_str,
+                    default_maildir_arg_str,
+		    (config_cache<mystring>&)maildir_arg_str_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_password_file.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_password_file("passwd");
+static const mystring filename_password_file = "password-file";
+mystring configuration::password_file() const {
+  return read_str(filename_password_file,
+                    default_password_file,
+		    (config_cache<mystring>&)password_file_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_postmaster_aliases.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static strlist default_postmaster_aliases(mystring("mailer-daemon\0postmaster\0root",29));
+static const mystring filename_postmaster_aliases = "postmaster-aliases";
+strlist configuration::postmaster_aliases() const {
+  return read_list(filename_postmaster_aliases,
+                    default_postmaster_aliases,
+		    (config_cache<strlist>&)postmaster_aliases_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_postmaster_email.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_postmaster_email("postmaster@");
+static const mystring filename_postmaster_email = "postmaster-email";
+mystring configuration::postmaster_email() const {
+  return read_str(filename_postmaster_email,
+                    default_postmaster_email,
+		    (config_cache<mystring>&)postmaster_email_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_qmail_root.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_qmail_root("/var/qmail");
+static const mystring filename_qmail_root = "qmail-root";
+mystring configuration::qmail_root() const {
+  return read_dir(filename_qmail_root,
+                    default_qmail_root,
+		    (config_cache<mystring>&)qmail_root_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_separators.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_separators("@:");
+static const mystring filename_separators = "separators";
+mystring configuration::separators() const {
+  return read_str(filename_separators,
+                    default_separators,
+		    (config_cache<mystring>&)separators_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_socket_file.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_socket_file("/tmp/.vmailmgrd");
+static const mystring filename_socket_file = "socket-file";
+mystring configuration::socket_file() const {
+  return read_str(filename_socket_file,
+                    default_socket_file,
+		    (config_cache<mystring>&)socket_file_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_user_dir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static mystring default_user_dir("users");
+static const mystring filename_user_dir = "user-dir";
+mystring configuration::user_dir() const {
+  return read_dir(filename_user_dir,
+                    default_user_dir,
+		    (config_cache<mystring>&)user_dir_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_user_dir_bits.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static unsigned default_user_dir_bits(0);
+static const mystring filename_user_dir_bits = "user-dir-bits";
+unsigned configuration::user_dir_bits() const {
+  return read_uns(filename_user_dir_bits,
+                    default_user_dir_bits,
+		    (config_cache<unsigned>&)user_dir_bits_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/_user_dir_slices.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static unsigned default_user_dir_slices(0);
+static const mystring filename_user_dir_slices = "user-dir-slices";
+unsigned configuration::user_dir_slices() const {
+  return read_uns(filename_user_dir_slices,
+                    default_user_dir_slices,
+		    (config_cache<unsigned>&)user_dir_slices_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/build-config.sh	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+newfile() {
+  local old=$1
+  local new=${old}.new
+  cat >$new
+  if cmp -s $old $new; then
+    echo "$old is unchanged." >&2
+    rm -f $new
+  else
+    echo "$old was changed, REPLACING." >&2
+    mv -f $new $old
+  fi
+}
+
+{
+  sed -e '/^%%LIST%%$/,$d' showvconfig.cc.in
+  while read type ext name default; do
+    filename=`echo $name | sed -e 's/_/-/g'`
+    sed -e "s|%NAME%|$name|g" \
+	-e "s|%EXT%|$ext|g" \
+	-e "s|%TYPE%|$type|g" \
+	-e "s|%DEFAULT%|$default|g" \
+	-e "s|%FILENAME%|$filename|g" \
+	configvar.in | newfile _${name}.cc
+    echo "  show_$ext(\"${filename}\", config->${name}());"
+  done <configrc.in
+  sed -e '1,/^%%LIST%%$/d' showvconfig.cc.in
+} | newfile showvconfig.cc
+
+{
+  sed -e '/^%%LIST%%$/,$d' configrc.h.in
+  while read type ext name default; do
+    echo "public: $type $name() const;"
+    echo "private: config_cache<$type> ${name}_cache;"
+  done <configrc.in
+  sed -e '1,/^%%LIST%%$/d' configrc.h.in
+} | newfile configrc.h
+
+{
+  sed -e '/^%%LIST%%$/,$d' Makefile.am.in
+  while read type ext name default; do
+    echo "	_${name}.cc \\"
+  done <configrc.in
+  sed -e '1,/^%%LIST%%$/d' Makefile.am.in
+} | newfile Makefile.am
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/config_read.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,30 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "mystring/mystring.h"
+#include "fdbuf/fdbuf.h"
+#include "configio.h"
+
+bool config_read(const mystring& dir, const mystring& name, mystring& result)
+{
+  mystring fullname = dir + "/" + name;
+  fdibuf in(fullname.c_str());
+  if(!in.getline(result))
+    return false;
+  result = result.strip();
+  return result.length() > 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/configio.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,16 @@
+#ifndef VMAILMGR__CONFIG_IO__H__
+#define VMAILMGR__CONFIG_IO__H__
+
+#include "mystring/mystring.h"
+#include "config/configrc.h"
+
+bool config_read(const mystring& dir, const mystring& name, mystring& result);
+
+#define cval(TYPE,FN,VAL,EXT) static TYPE default_##FN = VAL; \
+static mystring filename_##FN(#FN); \
+TYPE configuration:: FN () const { return read_##EXT (filename_##FN, default_##FN); }
+#define cval_str(FN,VAL) cval(mystring,FN,VAL,str)
+#define cval_dir(FN,VAL) cval(mystring,FN,VAL,dir)
+#define cval_uns(FN,VAL) cval(unsigned,FN,VAL,uns)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/configrc.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,42 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "mystring/mystring.h"
+#include "fdbuf/fdbuf.h"
+#include "configrc.h"
+
+#if 0
+configuration::configuration()
+  : parent(0)
+{
+}
+#endif
+
+configuration::configuration(const configuration* prev, const mystring& dir)
+  : parent(prev), directory(dir)
+{
+}
+
+configuration::~configuration()
+{
+}
+
+static configuration global_config(0, GLOBAL_CONFIG_DIR);
+const configuration* config = &global_config;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/configrc.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,92 @@
+#ifndef VMAILMGR__CONFIG_RC__H__
+#define VMAILMGR__CONFIG_RC__H__
+
+#ifndef GLOBAL_CONFIG_DIR
+#define GLOBAL_CONFIG_DIR "/etc/vmailmgr"
+#endif
+
+#ifndef LOCAL_CONFIG_DIR
+#define LOCAL_CONFIG_DIR ".vmailmgr"
+#endif
+
+#include "mystring/mystring.h"
+#include "misc/strlist.h"
+
+template<class T>
+struct config_cache
+{
+  T* value;
+  config_cache() : value(0) { }
+  ~config_cache() { delete value; }
+};
+
+class configuration 
+{
+public:
+  configuration();
+  configuration(const configuration* prev, const mystring& dir);
+  ~configuration();
+
+  configuration const * parent;
+
+  const mystring directory;
+
+public: mystring autoresponse_dir() const;
+private: config_cache<mystring> autoresponse_dir_cache;
+public: mystring autoresponse_file() const;
+private: config_cache<mystring> autoresponse_file_cache;
+public: mystring bulletin_dir() const;
+private: config_cache<mystring> bulletin_dir_cache;
+public: unsigned default_expiry() const;
+private: config_cache<unsigned> default_expiry_cache;
+public: mystring default_maildir() const;
+private: config_cache<mystring> default_maildir_cache;
+public: unsigned default_msgcount() const;
+private: config_cache<unsigned> default_msgcount_cache;
+public: unsigned default_msgsize() const;
+private: config_cache<unsigned> default_msgsize_cache;
+public: unsigned default_hardquota() const;
+private: config_cache<unsigned> default_hardquota_cache;
+public: unsigned default_softquota() const;
+private: config_cache<unsigned> default_softquota_cache;
+public: mystring default_username() const;
+private: config_cache<mystring> default_username_cache;
+public: mystring error_maildir() const;
+private: config_cache<mystring> error_maildir_cache;
+public: mystring global_bulletin_dir() const;
+private: config_cache<mystring> global_bulletin_dir_cache;
+public: mystring maildir_arg_str() const;
+private: config_cache<mystring> maildir_arg_str_cache;
+public: mystring password_file() const;
+private: config_cache<mystring> password_file_cache;
+public: strlist postmaster_aliases() const;
+private: config_cache<strlist> postmaster_aliases_cache;
+public: mystring postmaster_email() const;
+private: config_cache<mystring> postmaster_email_cache;
+public: mystring qmail_root() const;
+private: config_cache<mystring> qmail_root_cache;
+public: mystring separators() const;
+private: config_cache<mystring> separators_cache;
+public: mystring socket_file() const;
+private: config_cache<mystring> socket_file_cache;
+public: mystring user_dir() const;
+private: config_cache<mystring> user_dir_cache;
+public: unsigned user_dir_bits() const;
+private: config_cache<unsigned> user_dir_bits_cache;
+public: unsigned user_dir_slices() const;
+private: config_cache<unsigned> user_dir_slices_cache;
+
+private:
+  mystring read_str(const mystring& name, const mystring& def,
+                    config_cache<mystring>&) const;
+  mystring read_dir(const mystring& name, const mystring& def,
+                    config_cache<mystring>&) const;
+  unsigned read_uns(const mystring& name, unsigned def,
+                    config_cache<unsigned>&) const;
+  strlist read_list(const mystring& name, const strlist& def,
+                    config_cache<strlist>&) const;
+};
+
+extern const configuration* config;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/configrc.h.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,49 @@
+#ifndef VMAILMGR__CONFIG_RC__H__
+#define VMAILMGR__CONFIG_RC__H__
+
+#ifndef GLOBAL_CONFIG_DIR
+#define GLOBAL_CONFIG_DIR "/etc/vmailmgr"
+#endif
+
+#ifndef LOCAL_CONFIG_DIR
+#define LOCAL_CONFIG_DIR ".vmailmgr"
+#endif
+
+#include "mystring/mystring.h"
+#include "misc/strlist.h"
+
+template<class T>
+struct config_cache
+{
+  T* value;
+  config_cache() : value(0) { }
+  ~config_cache() { delete value; }
+};
+
+class configuration 
+{
+public:
+  configuration();
+  configuration(const configuration* prev, const mystring& dir);
+  ~configuration();
+
+  configuration const * parent;
+
+  const mystring directory;
+
+%%LIST%%
+
+private:
+  mystring read_str(const mystring& name, const mystring& def,
+                    config_cache<mystring>&) const;
+  mystring read_dir(const mystring& name, const mystring& def,
+                    config_cache<mystring>&) const;
+  unsigned read_uns(const mystring& name, unsigned def,
+                    config_cache<unsigned>&) const;
+  strlist read_list(const mystring& name, const strlist& def,
+                    config_cache<strlist>&) const;
+};
+
+extern const configuration* config;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/configrc.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,22 @@
+mystring dir	autoresponse_dir "autoresponse"
+mystring str	autoresponse_file "message.txt"
+mystring dir	bulletin_dir "bulletins"
+unsigned uns	default_expiry UINT_MAX
+mystring dir	default_maildir "Maildir"
+unsigned uns	default_msgcount UINT_MAX
+unsigned uns	default_msgsize UINT_MAX
+unsigned uns	default_hardquota UINT_MAX
+unsigned uns	default_softquota UINT_MAX
+mystring str	default_username "+"
+mystring dir	error_maildir "/var/lib/vmailmgr/error-maildir"
+mystring dir	global_bulletin_dir "/var/spool/bulletins"
+mystring str	maildir_arg_str "maildir"
+mystring str	password_file "passwd"
+strlist  list	postmaster_aliases mystring("mailer-daemon\\\\0postmaster\\\\0root",29)
+mystring str	postmaster_email "postmaster@"
+mystring dir	qmail_root "/var/qmail"
+mystring str	separators "@:"
+mystring str	socket_file "/tmp/.vmailmgrd"
+mystring dir	user_dir "users"
+unsigned uns	user_dir_bits 0
+unsigned uns	user_dir_slices 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/configvar.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "configio.h"
+#include <limits.h>
+
+static %TYPE% default_%NAME%(%DEFAULT%);
+static const mystring filename_%NAME% = "%FILENAME%";
+%TYPE% configuration::%NAME%() const {
+  return read_%EXT%(filename_%NAME%,
+                    default_%NAME%,
+		    (config_cache<%TYPE%>&)%NAME%_cache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/read_dir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,38 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "configrc.h"
+#include "configio.h"
+
+mystring configuration::read_dir(const mystring& file,
+				 const mystring& def,
+				 config_cache<mystring>& cache) const
+{
+  if(!cache.value) {
+    mystring result;
+    const configuration* node;
+    for(node = this; node; node = node->parent)
+      if(config_read(node->directory, file, result))
+	break;
+    if(!node)
+      result = def;
+    if(result[result.length()-1] != '/')
+      result += "/";
+    cache.value = new mystring(result);
+  }
+  return *cache.value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/read_list.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,37 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "configrc.h"
+
+strlist configuration::read_list(const mystring& file,
+				 const strlist& def,
+				 config_cache<strlist>& cache) const
+{
+  if(!cache.value) {
+    strlist result;
+    const configuration* node = this;
+    while(node)
+      if(result.read(node->directory + "/" + file))
+	break;
+      else
+	node = node->parent;
+    if(!node)
+      result = def;
+    cache.value = new strlist(result);
+  }
+  return *cache.value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/read_str.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,38 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "configrc.h"
+#include "configio.h"
+
+mystring configuration::read_str(const mystring& file,
+				 const mystring& def,
+				 config_cache<mystring>& cache) const
+{
+  if(!cache.value) {
+    mystring result;
+    const configuration* node;
+    for(node = this; node; node = node->parent)
+      if(config_read(node->directory, file, result)) {
+	cache.value = new mystring(result);
+	break;
+      }
+    if(!node)
+      result = def;
+    cache.value = new mystring(result);
+  }
+  return *cache.value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/read_uns.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,45 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "configrc.h"
+#include "configio.h"
+#include "misc/strtou.h"
+
+unsigned configuration::read_uns(const mystring& file,
+				 unsigned def,
+				 config_cache<unsigned>& cache) const
+{
+  if(!cache.value) {
+    mystring tmp;
+    unsigned result = 0;
+    const configuration* node;
+    for(node = this; node; node = node->parent) {
+      if(config_read(node->directory, file, tmp)) {
+	const char* endptr;
+	result = strtou(tmp.c_str(), &endptr);
+	if(endptr > tmp.c_str())
+	  break;
+      }
+    }
+    if(!node)
+      result = def;
+    cache.value = new unsigned(result);
+  }
+  return *cache.value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/showvconfig.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,81 @@
+#include <config.h>
+#include <limits.h>
+#include <unistd.h>
+#include "misc/pwentry.h"
+#include "vdomain/vdomain.h"
+#include "configrc.h"
+#include "fdbuf/fdbuf.h"
+
+template<class T>
+void show_val(const char* name, T value)
+{
+  fout << name << ": " << value << "\n\n";
+}
+
+void show_uns(const char* name, unsigned value)
+{
+  fout << name << ": ";
+  if(value == UINT_MAX)
+    fout << "-1\n\n";
+  else
+    fout << value << "\n\n";
+}
+
+void show_list(const char* name, const strlist& value)
+{
+  if(!value)
+    fout << name << " is empty.\n";
+  else
+    for(mystring_iter iter(value.str()); iter; ++iter)
+      fout << name << ": " << *iter << "\n";
+  fout << "\n";
+}
+
+#define show_dir show_val
+#define show_str show_val
+
+pwentry user;
+vdomain domain(user);
+
+bool go_home()
+{
+  if(!user.home) {
+    ferr << "showvconfig: Can't determine home directory" << endl;
+    return false;
+  }
+  if(chdir(user.home.c_str()) == -1) {
+    ferr << "showvconfig: Can't change to home directory" << endl;
+    return false;
+  }
+  config = &domain.config;
+  return true;
+}
+
+int main()
+{
+  if(!go_home())
+    return 1;
+  show_dir("autoresponse-dir", config->autoresponse_dir());
+  show_str("autoresponse-file", config->autoresponse_file());
+  show_dir("bulletin-dir", config->bulletin_dir());
+  show_uns("default-expiry", config->default_expiry());
+  show_dir("default-maildir", config->default_maildir());
+  show_uns("default-msgcount", config->default_msgcount());
+  show_uns("default-msgsize", config->default_msgsize());
+  show_uns("default-hardquota", config->default_hardquota());
+  show_uns("default-softquota", config->default_softquota());
+  show_str("default-username", config->default_username());
+  show_dir("error-maildir", config->error_maildir());
+  show_dir("global-bulletin-dir", config->global_bulletin_dir());
+  show_str("maildir-arg-str", config->maildir_arg_str());
+  show_str("password-file", config->password_file());
+  show_list("postmaster-aliases", config->postmaster_aliases());
+  show_str("postmaster-email", config->postmaster_email());
+  show_dir("qmail-root", config->qmail_root());
+  show_str("separators", config->separators());
+  show_str("socket-file", config->socket_file());
+  show_dir("user-dir", config->user_dir());
+  show_uns("user-dir-bits", config->user_dir_bits());
+  show_uns("user-dir-slices", config->user_dir_slices());
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/config/showvconfig.cc.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,60 @@
+#include <config.h>
+#include <limits.h>
+#include <unistd.h>
+#include "misc/pwentry.h"
+#include "vdomain/vdomain.h"
+#include "configrc.h"
+#include "fdbuf/fdbuf.h"
+
+template<class T>
+void show_val(const char* name, T value)
+{
+  fout << name << ": " << value << "\n\n";
+}
+
+void show_uns(const char* name, unsigned value)
+{
+  fout << name << ": ";
+  if(value == UINT_MAX)
+    fout << "-1\n\n";
+  else
+    fout << value << "\n\n";
+}
+
+void show_list(const char* name, const strlist& value)
+{
+  if(!value)
+    fout << name << " is empty.\n";
+  else
+    for(mystring_iter iter(value.str()); iter; ++iter)
+      fout << name << ": " << *iter << "\n";
+  fout << "\n";
+}
+
+#define show_dir show_val
+#define show_str show_val
+
+pwentry user;
+vdomain domain(user);
+
+bool go_home()
+{
+  if(!user.home) {
+    ferr << "showvconfig: Can't determine home directory" << endl;
+    return false;
+  }
+  if(chdir(user.home.c_str()) == -1) {
+    ferr << "showvconfig: Can't change to home directory" << endl;
+    return false;
+  }
+  config = &domain.config;
+  return true;
+}
+
+int main()
+{
+  if(!go_home())
+    return 1;
+%%LIST%%
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/COPYING	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,5 @@
+noinst_LIBRARIES = libauthmod.a
+EXTRA_DIST = COPYING README auth.h authmod.h authwait.h
+
+libauthmod_a_SOURCES = authexit.c authmod.c authmodfail.c \
+	chain.c changeuidgid.c copyargv.c success.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,290 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libauthmod.a
+EXTRA_DIST = COPYING README auth.h authmod.h authwait.h
+
+libauthmod_a_SOURCES = authexit.c authmod.c authmodfail.c 	chain.c changeuidgid.c copyargv.c success.c
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libauthmod_a_LIBADD = 
+libauthmod_a_OBJECTS =  authexit.o authmod.o authmodfail.o chain.o \
+changeuidgid.o copyargv.o success.o
+AR = ar
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  README COPYING Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libauthmod_a_SOURCES)
+OBJECTS = $(libauthmod_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/courier-authlib/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libauthmod.a: $(libauthmod_a_OBJECTS) $(libauthmod_a_DEPENDENCIES)
+	-rm -f libauthmod.a
+	$(AR) cru libauthmod.a $(libauthmod_a_OBJECTS) $(libauthmod_a_LIBADD)
+	$(RANLIB) libauthmod.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/courier-authlib
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+authexit.o: authexit.c
+authmod.o: authmod.c auth.h ../../config.h authmod.h authwait.h
+authmodclient.o: authmodclient.c authmod.h ../../config.h authwait.h
+authmodfail.o: authmodfail.c auth.h ../../config.h authmod.h
+authmoduser.o: authmoduser.c auth.h ../../config.h authmod.h authwait.h
+authmoduser2.o: authmoduser2.c auth.h ../../config.h authmod.h \
+	authwait.h
+authmoduser3.o: authmoduser3.c auth.h ../../config.h authmod.h
+chain.o: chain.c ../../config.h auth.h
+changeuidgid.o: changeuidgid.c ../../config.h auth.h
+copyargv.o: copyargv.c ../../config.h auth.h
+success.o: success.c auth.h ../../config.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/README	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,12 @@
+The contents of this directory have been taken intact from the "authlib"
+directory of the courier-imap package, version 0.30.31pre1.  The
+courier-imap package is distributed under the GPL, included in this
+directory.
+
+Courier-IMAP written by:
+
+Sam Varshavchik
+Double Precision, Inc.
+PO Box 668
+Greenwood Lake, NY 10925
+<mrsam@stop.mail-abuse.org>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/auth.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,186 @@
+#ifndef	auth_h
+#define	auth_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+#include	<sys/types.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+static const char auth_h_rcsid[]="$Id: auth.h,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+/*
+** authcopyargv prepares the arguments to execv for a module that receives
+** the next program to run, in a chain, via the command line.
+**
+** execv is documented to require a terminating null char **.  The fact
+** that argv is also null char ** is not always documented, and we can't
+** assume that.
+**
+** authcopyargv receives the new argc/argv arguments, and allocates a
+** new argv array.  argv[0] is stripped of any path, and the original
+** argv[0] is returned separately.
+*/
+
+extern char **authcopyargv(int,	/* argc */
+	char **,		/* argv */
+	char **);		/* original argv[0] */
+
+/*
+** authchain - chain to the next authentication module via exec.
+**
+** Runs the next authentication module, and passes it a copy of the
+** authentication request on file descriptor 3.
+**
+** authchain sets up a pipe on file descriptor 3, and forks.  The parent
+** runs the next authentication module.  The child sends the authentication
+** information down the pipe, and terminates.
+*/
+
+extern void authchain(int,	/* argc */
+	char **,		/* argv */
+	const char *);		/* Authentication request */
+
+/*
+** The following functions are used by root to reset its user and group id
+** to the authenticated user's.  Various functions are provided to handle
+** various situations.
+*/
+
+void authchangegroup(gid_t);	/* Set the group id only.  Also clear any
+				** auxiliary group ids */
+
+void authchangeuidgid(uid_t, gid_t);
+				/* Set both user id and group id.  Also clear
+				** aux group ids */
+
+void authchangeusername(const char *, const gid_t *);
+	/*
+	** Set the userid to the indicate user's.  If second argument is
+	** not null, it points to the groupid to set.  If it's null, the
+	** group id is taken from the passwd file.  Auxiliary IDs are set
+	** to any aux IDs set for the user in the group file.  If there are
+	** no aux group IDs for the user, any AUX ids are cleared.
+	*/
+
+/*
+** Authentication functions must call authsuccess if the authentication
+** request succeeds, and provide the following parameters.
+*/
+
+void authsuccess(
+		const char *,	/* home directory */
+		const char *,	/* username */
+		const uid_t	*,	/* userid */
+		const gid_t	*,	/* group id */
+
+		const char *,	/* AUTHADDR */
+		const char *);	/* AUTHFULLNAME */
+/*
+** EITHER username or userid can be specified (leave the other pointer null).
+** authmod_success changes to the home directory, and initializes the
+** process's uid and gid.  gid can be null if username is provided, in which
+** case gid will be picked up from the password file. gid CANNOT be null
+** if username is null.
+*/
+
+
+/* authcheckpassword is the general password validation routine.
+** It returns 0 if the password matches the encrypted password.
+*/
+
+int authcheckpassword(const char *,	/* password */
+	 const char *);			/* encrypted password */
+
+/* Stub function */
+
+extern void authexit(int);
+
+
+/*
+	LOW LEVEL AUTHENTICATION DRIVERS.
+
+Each low level authentication driver provides three functions:
+
+1) Primary authentication function.  This function is used to build a
+   standalone authentication module based on the mod.h template (see mod.h).
+   This function takes an authentication request.  If its valid, it
+   changes its userid/groupid to the one for the authenticated user,
+   changes the current directory to the authenticated user's home directory,
+   and sets the following environment variables:
+
+             MAILDIR - nondefault mailbox location (optional).
+
+2) User lookup function.  This function is prototyped as follows:
+
+     int functionname(const char *userid, const char *service,
+		int (*callback)(struct authinfo *, void *),
+			void *);
+
+     This function populates the following structure:
+*/
+
+struct authinfo {
+	const char *sysusername;
+	const uid_t *sysuserid;
+	gid_t sysgroupid;
+	const char *homedir;
+
+	const char *address;
+	const char *fullname;
+	const char *maildir;
+	const char *quota;
+
+	const char *passwd;
+	const char *clearpasswd;	/* For authldap */
+
+	unsigned staticindex;	/* When statically-linked functions are
+				** called, this holds the index of the
+				** authentication module in authstaticlist */
+
+	} ;
+
+/*
+	Either sysusername or sysuserid may be NULL, but not both of them.
+	They, and sysgroupid, specify the authenticated user's system
+	userid and groupid.  homedir points to the authenticated user's
+	home directory.  address, fullname, and maildir, are obvious.
+	quota is populated with any maildir quota (see
+	maildir/README.maildirquota).
+
+	After populating this tructure, the lookup function calls the
+	callback function that's specified in its second argument.  The
+	callback function receives a pointer to the authinfo structure.
+
+	The callback function also receives a context pointer, which is
+	the third argument to the lookup function.
+
+	The lookup function should return a negative value if he userid
+	does not exist, a positive value if there was a temporary error
+	looking up the userid, or whatever is the return code from the
+	callback function, if the user exists.
+
+
+NOTE: the passwd field is used internally by modules which implement
+the primary authentication function by sharing code with the lookup function.
+
+3) Cleanup function.  This function should close any resources that were
+   opened by the lookup function.  Note that in applications which have a
+   daemon process that uses this library it is possible for the lookup
+   function to be called multiple times, before the cleanup function is
+   called.
+*/
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/authexit.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,13 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#include	<stdlib.h>
+
+static const char rcsid[]="$Id: authexit.c,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+void authexit(int rc)
+{
+	exit(rc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/authmod.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,101 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#include	"auth.h"
+#include	"authmod.h"
+#include	"authwait.h"
+#include	<stdio.h>
+#include	<string.h>
+#include	<stdlib.h>
+#include	<signal.h>
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+
+static const char rcsid[]="$Id: authmod.c,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+static char	authrec[BUFSIZ];
+static char	buf[BUFSIZ];
+
+void	authmod_init(
+		int argc,
+		char **argv,
+		const char **service,
+		const char **authtype,
+		char **authdata)
+{
+FILE	*fpin;
+int	waitstat;
+const char *a=getenv("AUTHENTICATED");
+char	*p;
+int	n;
+
+	if (a && *a)	/* Already a good guy */
+		authmod_success(argc, argv, a);
+
+	n=0;
+	fpin=fdopen(3, "r");
+	if (fpin)
+	{
+	int	c;
+
+		while ((c=getc(fpin)) != EOF)
+			if (n < sizeof(buf)-1)
+				buf[n++]=c;
+		buf[n]=0;
+	}
+
+	if (n == 0)
+	{
+		write(2, "AUTHFAILURE\n", 12);
+		authexit(1);
+	}
+
+	fclose(fpin);
+	close(3);	/* Insurance */
+	strcpy(authrec, buf);
+
+	signal(SIGCHLD, SIG_DFL);
+
+	while (wait(&waitstat) >= 0)
+		;
+
+	p=buf;
+	*service=p;
+	while (*p && *p != '\n')
+		++p;
+	if (*p)	*p++=0;
+	*authtype=p;
+	while (*p && *p != '\n')
+		++p;
+	if (*p)	*p++=0;
+	*authdata=p;
+}
+
+void authmod_success(int argc, char **argv, const char *a)
+{
+char	**vec, *prog;
+char	*b;
+
+	vec=authcopyargv(argc-1, argv+1, &prog);
+	if (!prog)	authexit(1);
+
+	b=malloc(sizeof("AUTHENTICATED=")+strlen(a));
+	if (!b)
+	{
+		perror("malloc");
+		authexit(1);
+	}
+	strcat(strcpy(b, "AUTHENTICATED="), a);
+	putenv(b);
+	execv(prog, vec);
+	perror("exec");
+	authexit(1);
+}
+
+void authmod_fail(int argc, char **argv)
+{
+	authchain(argc-1, argv+1, authrec);	/* Next module */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/authmod.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,137 @@
+#ifndef	authmod_h
+#define	authmod_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+/* Common functions used by standalone authentication modules */
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+static const char authmod_h_rcsid[]="$Id: authmod.h,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+/*
+** Authentication modules must call authmod_init the first thing in main.
+*/
+
+void	authmod_init(
+		int,		/* argc */
+		char **,	/* argv */
+
+		const char **,	/* Returns service to authenticate */
+		const char **,	/* Returns authentication type */
+		char **);	/* Returns authentication data */
+
+/*
+** NOTE: authmod_init does NOT return if a previous authentication module
+** already succesfully authenticated the request.  authmod_init will run the
+** next module automatically, hence we'll eventually wind up with the
+** authentication client in the authenticated state.
+**
+** An authentication module must call authmod_success if it accepted the
+** authentication request.
+*/
+
+void authmod_success(int,	/* argc */
+		char **,	/* argv */
+		const char *);	/* authenticated_username */
+
+/*
+** Standalone modules should call authmod_fail if the authentication failed.
+*/
+
+void authmod_fail(int,		/* argc */
+		char **);	/* argv */
+
+/*
+** Standalone modules should call authmod_fail_completely, and if the module
+** does not want any additional authentication modules to try to authenticate
+** this request.  authmod_fail_completely reruns the authentication user
+** process (see below).
+*/
+
+void authmod_fail_completely();
+
+/*
+** authentication clients should call authclient() the first thing in main,
+** to check if the authentication succeeded.  If not, authclient terminates
+** the process and reruns the authmoduser process
+*/
+
+const char *authmodclient();
+
+/*
+** authmoduser is called by authentication users as the very first thing
+** in main().  It checks the environment variables and returns 0 if
+** auth user was reinvoked upon authentication failure.  It returns non-0
+** if this is the initial invocation of the auth user process.
+**
+** authmoduser:
+**
+**    * checks to make sure the environment variable AUTHUSER is set, which
+**      should contain the full pathname to this process (can't rely on
+**      argv[0] all the time).  authmoduser terminates if AUTHUSER is not set.
+**
+**    * checks if the environment variable AUTHARGC is set to a non-zero
+**      value.  If it is, it means AUTHUSER was rerun due to an authentication
+**      failure, so authmoduser will return 0, after sleeping for the amount
+**      of time specified by the fourth argument.
+**
+**    * otherwise the environment variables AUTHARGC, AUTHARGV0, AUTHARGV1 ...
+**      are set to mirror the contents of the argc/argv variables, so that
+**      upon authentication failure $AUTHUSER can be rerun, with the same
+**      exact parameters.
+**
+** The third argument to authmoduser specifies the timeout for a successful
+** login.  The expiration time is also saved in the environment, and
+** authmoduser will call alarm() to cause this process to die if the authmod()
+** function is not called before the timer goes off.  The authmod function
+** will cancel the alarm signal before running the first authentication
+** module, in order to avoid arrivals of unexpected signals.
+**
+*/
+
+int authmoduser(int,		/* argc - as passed to main */
+		char **,	/* argv - as passed to main */
+
+		unsigned,	/* authentication timeout, in seconds */
+		unsigned);	/* bad authentication sleep time, in seconds */
+
+
+/*
+** authmod is called by authentication user to attempt to authenticate
+** access.  This function never returns as it execs the first authentication
+** module.  The authentication module to run is taken from the argv[0]
+** parameter (see below) and argc must be > 0.  This means that argc/argv
+** received by main must be advanced to skip past any options on the command
+** line.
+*/
+
+#define	AUTHTYPE_LOGIN	"login"		/* authdata is userid\npassword\n */
+#define	AUTHTYPE_CRAMMD5 "cram-md5"	/* authdata is challenge\nresponse\n */
+
+void authmod(int,	/* argc */
+	char **,	/* argv */
+
+	const char *,	/* service */
+	const char *,	/* authentication type */
+	const char *);	/* authentication data */
+
+void authmod_login(int,
+	char **,
+	const char *,	/* service */
+	const char *,	/* userid */
+	const char *);	/* password */
+
+#ifdef	__cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/authmodfail.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,52 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#include	"auth.h"
+#include	"authmod.h"
+#include	<stdio.h>
+#include	<string.h>
+#include	<stdlib.h>
+#include	<signal.h>
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+
+static const char rcsid[]="$Id: authmodfail.c,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+void	authmod_fail_completely()
+{
+char	**argv;
+int	argc, n;
+const char *p=getenv("AUTHARGC");
+char	buf[20];
+
+	if (!p || sscanf(p, "%d", &argc) <= 0 || argc <= 0)
+	{
+		write(2, "AUTHFAILURE\n", 12);
+		authexit(1);
+	}
+
+	if ((argv=(char **)malloc((argc+1)*sizeof(char *))) == 0)
+	{
+		perror("malloc");
+		authexit(1);
+	}
+
+	for (n=0; n<argc; n++)
+	{
+		sprintf(buf, "AUTHARGV%d", n);
+		if ((argv[n]=getenv(buf)) == 0)
+			authexit(1);
+	}
+	argv[n]=0;
+
+	p=getenv("AUTHUSER");
+	if (!p)
+		authexit(1);
+
+	execv(p, argv);
+	perror(p);
+	authexit(1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/authwait.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,26 @@
+#ifndef	authwait_h
+#define	authwait_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+
+static const char authwait_h_rcsid[]="$Id: authwait.h,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+#include <sys/types.h>
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/chain.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,67 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<string.h>
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+#if	HAVE_FCNTL_H
+#include	<fcntl.h>
+#endif
+
+#include	"auth.h"
+
+static const char rcsid[]="$Id: chain.c,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+void authchain(int argc, char **argv, const char *buf)
+{
+int	pipes[2];
+pid_t	p;
+int	l, n;
+char	**vec;
+char	*prog;
+
+	vec=authcopyargv(argc, argv, &prog);
+	if (!prog || open("/dev/null", O_RDONLY) != 3)	authexit(1);
+
+	if (pipe(pipes))
+	{
+		perror("pipe");
+		authexit(1);
+	}
+	while ((p=fork()) < 0)
+	{
+		perror("fork");
+		sleep(3);
+	}
+	close(3);
+
+	if (p)
+	{
+		dup(pipes[0]);
+		close(pipes[0]);
+		close(pipes[1]);
+		execv(prog, vec);
+		perror(prog);
+		authexit(1);
+	}
+	l=strlen(buf);
+	close(3);
+	close(pipes[0]);
+	while (l)
+	{
+		n=write(pipes[1], buf, l);
+		if (n <= 0)	break;
+		buf += n;
+		l -= n;
+	}
+	close(pipes[1]);
+	authexit(1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/changeuidgid.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,110 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+#include	<sys/types.h>
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<grp.h>
+#include	<pwd.h>
+#include	<errno.h>
+
+#include	"auth.h"
+
+static const char rcsid[]="$Id: changeuidgid.c,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+void authchangegroup(gid_t gid)
+{
+	if ( setgid(gid))
+	{
+		perror("setgid");
+		authexit(1);
+	}
+
+#if HAVE_SETGROUPS
+	if ( getuid() == 0 && setgroups(1, &gid) )
+	{
+		perror("setgroups");
+		authexit(1);
+	}
+#endif
+}
+
+void authchangeuidgid(uid_t uid, gid_t gid)
+{
+	authchangegroup(gid);
+	if ( setuid(uid))
+	{
+		perror("setuid");
+		authexit(1);
+	}
+}
+
+void authchangeusername(const char *uname, const gid_t *forcegrp)
+{
+struct passwd *pw;
+uid_t	changeuid;
+gid_t	changegid;
+
+/* uname might be a pointer returned from a previous called to getpw(),
+** and libc has a problem getting it back.
+*/
+char	*p=malloc(strlen(uname)+1);
+
+	if (!p)
+	{
+		perror("malloc");
+		authexit(1);
+	}
+	strcpy(p, uname);
+
+	errno=ENOENT;
+	if ((pw=getpwnam(p)) == 0)
+	{
+		free(p);
+		perror("getpwnam");
+		authexit(1);
+	}
+	free(p);
+
+	changeuid=pw->pw_uid;
+
+	if ( !forcegrp )	forcegrp= &pw->pw_gid;
+
+	changegid= *forcegrp;
+
+	if ( setgid( changegid ))
+	{
+		perror("setgid");
+		authexit(1);
+	}
+
+#if HAVE_INITGROUPS
+	if ( getuid() == 0 && initgroups(pw->pw_name, changegid) )
+	{
+		perror("initgroups");
+		authexit(1);
+	}
+#else
+#if HAVE_SETGROUPS
+	if ( getuid() == 0 && setgroups(1, &changegid) )
+	{
+		perror("setgroups");
+		authexit(1);
+	}
+#endif
+#endif
+
+	if (setuid(changeuid))
+	{
+		perror("setuid");
+		authexit(1);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/copyargv.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,40 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<string.h>
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+#include	"auth.h"
+
+static const char rcsid[]="$Id: copyargv.c,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+char **authcopyargv(int c, char **oldv, char **prog)
+{
+char **v;
+int	n;
+
+	if ((v=(char **)malloc(sizeof(char *)*(c+1))) == 0)
+	{
+		perror("malloc");
+		authexit(1);
+	}
+	for (n=0; n<c; n++)
+		v[n]=oldv[n];
+	v[c]=0;
+	if (v[0])
+	{
+		*prog=v[0];
+	}
+	else
+		*prog=0;
+
+	return (v);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/courier-authlib/success.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,84 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#include	"auth.h"
+
+#include	<stdio.h>
+#include	<errno.h>
+#include	<stdlib.h>
+#include	<string.h>
+
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+
+static const char rcsid[]="$Id: success.c,v 1.1 2000/04/13 17:55:05 bruce Exp $";
+
+void authsuccess(const char *homedir,
+	const char *username,
+	const uid_t	*uid,
+	const gid_t	*gid,
+	const char	*authaddr,
+	const char	*authfullname)
+{
+static char	*authaddr_buf=0;
+static char	*authfullname_buf=0;
+char	*p;
+
+	if (chdir(homedir))
+	{
+		perror("chdir");
+		authexit(1);
+	}
+
+	if (username)
+	{
+		if (gid)
+			authchangegroup(*gid);
+		authchangeusername(username, gid);
+	}
+	else
+	{
+		if (!uid || !gid)
+		{
+			write(2, "AUTHFAILURE\n", 12);
+			authexit(1);
+		}
+		authchangeuidgid(*uid, *gid);
+	}
+
+	if (!authaddr)	authaddr="";
+	if (authaddr_buf)	free(authaddr_buf);
+	authaddr_buf=malloc(sizeof("AUTHADDR=")+strlen(authaddr));
+	if (!authaddr_buf)
+	{
+		perror("malloc");
+		authexit(1);
+	}
+	strcat(strcpy(authaddr_buf, "AUTHADDR="), authaddr);
+
+	if (!authfullname)	authfullname="";
+	if (authfullname_buf)	free(authfullname_buf);
+	authfullname_buf=malloc(sizeof("AUTHFULLNAME=")+strlen(authfullname));
+	if (!authfullname_buf)
+	{
+		perror("malloc");
+		authexit(1);
+	}
+	strcat(strcpy(authfullname_buf, "AUTHFULLNAME="), authfullname);
+
+	/* Get rid of GECOS crud */
+
+	p=authfullname_buf+strlen(authfullname_buf);
+	while (*--p == ',')
+		*p=0;
+	putenv(authaddr_buf);
+	putenv(authfullname_buf);
+}
+
+void authdummy()
+{
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/ChangeLog	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,161 @@
+2000-08-22  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* Added the missing accessor for the internal "errnum" data member
+	to the fdibuf and fdobuf classes.
+
+2000-08-10  Bruce Guenter  <bruce@bruce-guenter.dyndns.org>
+
+	* fdibuf.cc (read_large): Fixed a bug in the increment of data.
+
+	* fdibuf_mystring.cc (getline): Reduced some of the expressions
+	into variables.
+
+2000-04-08  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* fdibuf.cc (read_large): Fixed bug: count needed to be
+	incremented after reading data in.
+
+2000-04-07  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* fdobuf_signed.cc (operator<<): Immediately output a '-' for
+	negative numbers rather than storing a negative flag for later.
+
+	* fdobuf_unsigned.cc (operator<<): Moved the integer versions of
+	this operator into their own modules.
+
+	* fdobuf_seek.cc (seek): Moved this routine out of fdobuf.cc
+
+	* fdibuf.cc (read_large): Added this routine to read in a chunk of
+	data larger than the size of the buffer.
+
+2000-04-06  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* fdibuf_netstring.cc (getnetstring): Moved this routine into its
+	own source file.
+
+	* fdobuf.cc (write_large): Added this routine to write out a chunk
+	of data larger than the size of the buffer, to avoid doing extra
+	copies.
+	(write): Removed an extraneous code segment.
+
+	* fdobuf.h: Moved the fdobuf declarations here.
+
+	* fdibuf.h: Moved the fdibuf declarations here.
+
+	* fdbuf.h: Removed extraneous fdobuf declaration.
+
+1999-07-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf.cc (write): Optimized this routine better for the case
+	where the amount of data to be written will fit inside the buffer.
+
+1999-07-05  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdbuf.h (fdobuf,fdibuf): Made some of the routines here virtual
+	in order to extend it properly.
+	Added "tell()" operations to both fdibuf and fdobuf to indicate
+	the current logical read/write point.
+
+1999-07-04  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf_chownmod.cc: Added two new routines chown and chmod,
+	which operate directly on the open fd.
+
+1999-06-30  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdibuf_mystring.cc (getline): Make this routine return the
+	number of bytes actually read, including the delimiter, even
+	though the delimiter is not added to the returned string.
+
+1999-06-29  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdibuf.cc (fdibuf): Added a 'seekfwd' function to seek forwards
+	"o" bytes.
+
+	* fdibuf_mystring.cc (getline): Added locking and set the count
+	properly.
+
+1999-06-28  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdibuf.cc (get): Make sure count is set for get.
+
+1999-06-06  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdbuf.cc (fdbuf): Fixed long-standing bug -- I forgot to delete
+	the buffer in the destructor.
+	(close): Modified the code to ensure that the fd is not closed
+	twice (as would happen when destructing the fdbuf).
+
+1999-05-31  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf.cc: Redefined flush as nflush; added sync code to nflush;
+	made flush and sync call nflush; added mutex lock calls to all
+	public methods.
+
+	* fdibuf.cc: Added mutex lock calls to all public methods.
+
+	* fdbuf.cc: Added debugging implementations of lock() and unlock()
+	mutex operators (to be removed before real use).
+
+1999-05-28  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf.cc (fdobuf): Fixed missing initialization of bufpos in
+	one of the two constructors.
+
+1999-05-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf.cc (fdobuf): Added an optional "mode" parameter which
+	defaults to 0666, which is the permissions for the new file.
+	(sync): Wrote this function to fsync the file descriptor.
+
+1999-04-27  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdbuf.h (fdobuf): Removed definition for sync and nonblock mode,
+	as they won't be handled correctly in the writing code.
+
+1999-04-03  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf.cc (operator<<): Wrote an operator for signed and
+	unsigned longs, with overloaded functions for ints and shorts that
+	promote the parameters to longs.
+	(write): Wrote a write routine specifically for a single
+	character.
+
+1999-04-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf.cc: Fixed handling of seek by adding a "bufpos" indicator
+	that points to the current position in the buffer at which writes
+	should go.  buflength is effectively the maximum value of bufpos
+	between flushes.
+
+	* fdibuf.cc (get): Renamed getchar to get (to be potentially
+	overloaded with other types).
+
+	* fdbuf.h (fdbuf): Removed a bunch of write methods and replaced
+	them with "operator<<", with similar capability to iostreams
+	methods of the same names.
+
+	* fdobuf.cc (endl): Wrote this manipulator to write an end-of-line
+	and flush the buffer.
+
+1999-03-31  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* fdobuf_mystring.cc: Moved all the mystring-specific code from
+	fdobuf.cc into this module to lessen link problems.
+
+	* fdibuf_mystring.cc: Moved all the mystring-specific code from
+	fdibuf.cc into this module to lessen link problems.
+
+	* fdobuf.cc (seek): Wrote this seek routine to allow movement in
+	an output file buffer.
+
+	* fdibuf.cc (seek): Generalized the rewind routine to allow
+	arbitrary seeks.  It also checks to see if the seek point is
+	within the current buffer and if so just repositions its
+	pointers.
+
+	* fdbuf.h: If BUFSIZE is not defined, set it here to 4096.
+	(class fdbuf ): Rename length, start, and size to buflength,
+	bufstart, and bufsize.  Add a new field "offset" to indicate the
+	current file seek offset.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,22 @@
+noinst_LIBRARIES = libfdbuf.a
+INCLUDES = -I..
+
+if FDBUF_NO_MYSTRING
+mystring_sources =
+else
+mystring_sources = fdibuf_mystring.cc fdibuf_netstring.cc
+endif
+
+libfdbuf_a_SOURCES = \
+	fdbuf.h \
+	fdbuf.cc \
+	fdbuf_copy.cc \
+	fdibuf.h \
+	fdibuf.cc \
+	fdobuf.h \
+	fdobuf.cc \
+	fdobuf_chownmod.cc \
+	fdobuf_seek.cc \
+	fdobuf_signed.cc \
+	fdobuf_unsigned.cc \
+	$(mystring_sources)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,314 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libfdbuf.a
+INCLUDES = -I..
+@FDBUF_NO_MYSTRING_TRUE@mystring_sources = 
+@FDBUF_NO_MYSTRING_FALSE@mystring_sources = fdibuf_mystring.cc fdibuf_netstring.cc
+
+libfdbuf_a_SOURCES =  	fdbuf.h 	fdbuf.cc 	fdbuf_copy.cc 	fdibuf.h 	fdibuf.cc 	fdobuf.h 	fdobuf.cc 	fdobuf_chownmod.cc 	fdobuf_seek.cc 	fdobuf_signed.cc 	fdobuf_unsigned.cc 	$(mystring_sources)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libfdbuf_a_LIBADD = 
+@FDBUF_NO_MYSTRING_FALSE@libfdbuf_a_OBJECTS =  fdbuf.o fdbuf_copy.o \
+@FDBUF_NO_MYSTRING_FALSE@fdibuf.o fdobuf.o fdobuf_chownmod.o \
+@FDBUF_NO_MYSTRING_FALSE@fdobuf_seek.o fdobuf_signed.o \
+@FDBUF_NO_MYSTRING_FALSE@fdobuf_unsigned.o fdibuf_mystring.o \
+@FDBUF_NO_MYSTRING_FALSE@fdibuf_netstring.o
+@FDBUF_NO_MYSTRING_TRUE@libfdbuf_a_OBJECTS =  fdbuf.o fdbuf_copy.o \
+@FDBUF_NO_MYSTRING_TRUE@fdibuf.o fdobuf.o fdobuf_chownmod.o \
+@FDBUF_NO_MYSTRING_TRUE@fdobuf_seek.o fdobuf_signed.o fdobuf_unsigned.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  ChangeLog Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libfdbuf_a_SOURCES)
+OBJECTS = $(libfdbuf_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/fdbuf/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libfdbuf.a: $(libfdbuf_a_OBJECTS) $(libfdbuf_a_DEPENDENCIES)
+	-rm -f libfdbuf.a
+	$(AR) cru libfdbuf.a $(libfdbuf_a_OBJECTS) $(libfdbuf_a_LIBADD)
+	$(RANLIB) libfdbuf.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/fdbuf
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+fdbuf.o: fdbuf.cc fdbuf.h ../../config.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+fdbuf_copy.o: fdbuf_copy.cc fdbuf.h ../../config.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+fdibuf.o: fdibuf.cc fdbuf.h ../../config.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+fdibuf_mystring.o: fdibuf_mystring.cc fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h
+fdibuf_netstring.o: fdibuf_netstring.cc fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h
+fdobuf.o: fdobuf.cc fdbuf.h ../../config.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+fdobuf_chownmod.o: fdobuf_chownmod.cc fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+fdobuf_seek.o: fdobuf_seek.cc fdbuf.h ../../config.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+fdobuf_signed.o: fdobuf_signed.cc fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+fdobuf_unsigned.o: fdobuf_unsigned.cc fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdbuf.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,107 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "fdbuf.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// Class fdbuf
+///////////////////////////////////////////////////////////////////////////////
+fdbuf::fdbuf(int fdesc, bool dc, unsigned bufsz)
+  : buf(new char[bufsz]),
+    buflength(0),
+    bufstart(0),
+    offset(0),
+    errnum(0),
+    flags(0),
+    bufsize(bufsz),
+    fd(fdesc),
+    do_close(dc)
+{
+  if(!buf) {
+    flags = flag_error;
+    errnum = errno;
+  }
+  if(fdesc < 0)
+    flags |= flag_closed;
+#ifdef _REENTRANT
+  pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER;
+  mutex = tmp;
+  pthread_mutex_init(&mutex, 0);
+#else
+#ifdef FDBUF_MUTEX_DEBUG
+  mutex_count = 0;
+#endif
+#endif
+}
+
+fdbuf::~fdbuf()
+{
+  close();
+#ifdef _REENTRANT
+  pthread_mutex_destroy(&mutex);
+#endif
+  delete buf;
+}
+
+bool fdbuf::error() const
+{
+  return flags & flag_error;
+}
+
+bool fdbuf::closed() const
+{
+  return flags & flag_closed;
+}
+
+bool fdbuf::close()
+{
+  if(do_close && fd >= 0 && !(flags & flag_closed)) {
+    if(::close(fd) == -1) {
+      errnum = errno;
+      flags |= flag_error;
+      return false;
+    }
+    flags |= flag_closed;
+  }
+  return true;
+}
+
+#if defined(FDBUF_MUTEX_DEBUG) && !defined(_REENTRANT)
+{
+  int* null = 0;
+  (*null)++;
+  kill(getpid(), 9);
+}
+
+// Debugging code
+void fdbuf::lock()
+{
+  if(mutex)
+    abort();
+  ++mutex;
+}
+
+void fdbuf::unlock()
+{
+  if(mutex != 1)
+    abort();
+  --mutex;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdbuf.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,82 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef FDBUF__H__
+#define FDBUF__H__
+
+#include "config.h"
+#include <string.h>
+#include <fcntl.h>
+
+#ifdef _REENTRANT
+#include <pthread.h>
+#endif
+
+#ifndef FDBUF_SIZE
+#define FDBUF_SIZE 4096
+#endif
+
+class mystring;
+
+class fdbuf 
+{
+public:
+  enum flagbits { flag_eof=1, flag_error=2, flag_closed=4 };
+
+  fdbuf(int fdesc, bool dc, unsigned bufsz = FDBUF_SIZE);
+  ~fdbuf();
+  bool error() const;
+  bool closed() const;
+  bool close();
+#ifdef _REENTRANT
+  void lock() { pthread_mutex_lock(&mutex); }
+  void unlock() { pthread_mutex_unlock(&mutex); }
+#else
+#ifdef FDBUF_MUTEX_DEBUG
+  void lock();
+  void unlock();
+#else
+  void lock() { }
+  void unlock() { }
+#endif
+#endif
+protected:
+  char* const buf;
+  unsigned buflength;		// Length of the data in the buffer
+  unsigned bufstart;		// Start of the data in the buffer
+  unsigned offset;		// Current file read/write offset
+  int errnum;			// Saved error flag
+  unsigned flags;		// Status flags
+
+  const unsigned bufsize;	// Total buffer size
+  const int fd;
+  const bool do_close;		// True to close on destructor
+
+#ifdef _REENTRANT
+  pthread_mutex_t mutex;
+#else
+#ifdef FDBUF_MUTEX_DEBUG
+  unsigned mutex;
+#endif
+#endif
+};
+
+#include "fdbuf/fdibuf.h"
+#include "fdbuf/fdobuf.h"
+
+bool fdbuf_copy(fdibuf&, fdobuf&, bool noflush = false);
+
+#endif // FDBUF__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdbuf_copy.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,38 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "fdbuf.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Other routines
+///////////////////////////////////////////////////////////////////////////////
+bool fdbuf_copy(fdibuf& in, fdobuf& out, bool noflush)
+{
+  if(in.eof())
+    return true;
+  if(!in || !out)
+    return false;
+  do {
+    char buf[FDBUF_SIZE];
+    if(!in.read(buf, FDBUF_SIZE) && in.last_count() == 0)
+      break;
+    if(!out.write(buf, in.last_count()) && out.last_count() < in.last_count())
+      return false;
+  } while(!in.eof());
+  if(!noflush && !out.flush())
+    return false;
+  return in.eof();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdibuf.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,192 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "fdbuf.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// Class fdibuf
+///////////////////////////////////////////////////////////////////////////////
+fdibuf::fdibuf(int fdesc, bool dc, unsigned bufsz)
+  : fdbuf(fdesc, dc, bufsz)
+{
+}
+
+fdibuf::fdibuf(const char* filename, unsigned bufsz)
+  : fdbuf(open(filename, O_RDONLY), true, bufsz)
+{
+  if(fd == -1) {
+    flags = flag_error;
+    errnum = errno;
+  }
+}
+
+fdibuf::~fdibuf()
+{
+}
+
+bool fdibuf::eof() const
+{
+  return (flags & flag_eof) && (bufstart >= buflength);
+}
+
+bool fdibuf::operator!() const
+{
+  return eof() || error() || closed();
+}
+
+// refill is protected -- no locking
+bool fdibuf::refill()
+{
+  if(flags)
+    return false;
+  if(bufstart != 0) {
+    if(bufstart < buflength) {
+      buflength -= bufstart;
+      memcpy(buf, buf+bufstart, buflength);
+    } else
+      buflength = 0;
+    bufstart = 0;
+  }
+  unsigned oldbuflength = buflength;
+  if(buflength < bufsize) {
+    ssize_t red = ::read(fd, buf+buflength, bufsize-buflength);
+    if(red == -1) {
+      errnum = errno;
+      flags |= flag_error;
+    }
+    else if(red == 0)
+      flags |= flag_eof;
+    else {
+      buflength += red;
+      offset += red;
+    }
+  }
+  return buflength > oldbuflength;
+}
+
+bool fdibuf::get(char& ch)
+{
+  lock();
+  count = 0;
+  if(bufstart >= buflength)
+    refill();
+  bool r = true;
+  if(eof() || error())
+    r = false;
+  else {
+    ch = buf[bufstart++];
+    count = 1;
+  }
+  unlock();
+  return r;
+}
+
+bool fdibuf::read_large(char* data, unsigned datalen)
+{
+  lock();
+  count = 0;
+
+  // If there's any content in the buffer, memcpy it out first.
+  unsigned len = buflength - bufstart;
+  if(len > datalen)
+    len = datalen;
+  memcpy(data, buf+bufstart, len);
+  data += len;
+  datalen -= len;
+  bufstart += len;
+  count += len;
+
+  // After the buffer is empty and there's still data to read,
+  // read it straight from the fd instead of copying it through the buffer.
+  while(datalen > 0) {
+    ssize_t red = ::read(fd, data, datalen);
+    if(red == -1) {
+      errnum = errno;
+      flags |= flag_error;
+      break;
+    }
+    else if(red == 0) {
+      flags |= flag_eof;
+      break;
+    }
+    data += red;
+    datalen -= red;
+    offset += red;
+    count += red;
+  }
+  unlock();
+  return datalen == 0;
+}
+
+bool fdibuf::read(char* data, unsigned datalen)
+{
+  if(datalen >= bufsize)
+    return read_large(data, datalen);
+  lock();
+  count = 0;
+  char* ptr = data;
+  while(datalen && !eof()) {
+    if(bufstart >= buflength)
+      refill();
+    unsigned len = buflength-bufstart;
+    if(len > datalen)
+      len = datalen;
+    memcpy(ptr, buf+bufstart, len);
+    bufstart += len;
+    datalen -= len;
+    ptr += len;
+    count += len;
+  }
+  unlock();
+  return !datalen;
+}
+
+bool fdibuf::seek(unsigned o)
+{
+  lock();
+  unsigned buf_start = offset - buflength;
+  if(o >= buf_start && o < offset) {
+    bufstart = o - buf_start;
+  }
+  else {
+    if(lseek(fd, o, SEEK_SET) != (off_t)o) {
+      errnum = errno;
+      flags |= flag_error;
+      unlock();
+      return false;
+    }
+    offset = o;
+    buflength = bufstart = 0;
+  }
+  count = 0;
+  flags &= ~flag_eof;
+  unlock();
+  return true;
+}
+
+bool fdibuf::seekfwd(unsigned o)
+{
+  return seek(tell() + o);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Globals
+///////////////////////////////////////////////////////////////////////////////
+fdibuf fin(0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdibuf.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,50 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef FDBUF__FDIBUF__H__
+#define FDBUF__FDIBUF__H__
+
+class fdibuf : protected fdbuf
+{
+public:
+  fdibuf(const char* filename, unsigned bufsz = FDBUF_SIZE);
+  fdibuf(int fdesc, bool dc = false, unsigned bufsz = FDBUF_SIZE);
+  virtual ~fdibuf();
+  bool close() { lock(); bool r = fdbuf::close(); unlock(); return r; }
+  bool eof() const;
+  bool operator!() const ;
+  operator bool() const { return !operator!(); }
+  virtual bool get(char& ch);
+  virtual bool getline(mystring& out, char terminator = '\n');
+  virtual bool getnetstring(mystring& out);
+  virtual bool read(char*, unsigned);
+  virtual bool read_large(char*, unsigned);
+  bool read(unsigned char* b, unsigned l) { return read((char*)b, l); }
+  bool read(signed char* b, unsigned l) { return read((char*)b, l); }
+  unsigned last_count() { return count; }
+  bool seek(unsigned o);
+  bool seekfwd(unsigned o);
+  bool rewind() { return seek(0); }
+  unsigned tell() const { return offset-buflength+bufstart; }
+  int error_number() const { return errnum; }
+protected:
+  unsigned count;		// Number of bytes read by last operation
+  bool refill();
+};
+
+extern fdibuf fin;
+
+#endif // FDBUF__FDIBUF__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdibuf_mystring.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,52 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <string.h>
+#include "fdbuf.h"
+#include "mystring/mystring.h"
+
+bool fdibuf::getline(mystring& out, char terminator)
+{
+  lock();
+  count = 0;
+  if(bufstart >= buflength)
+    refill();
+  if(eof() || error()) {
+    unlock();
+    return false;
+  }
+  out = "";
+  while(!eof() && !error()) {
+    char* ptr = buf+bufstart;
+    unsigned bufleft = buflength - bufstart;
+    const char* end = (const char*)memchr(ptr, terminator, bufleft);
+    if(!end) {
+      out += mystring(ptr, bufleft);
+      bufstart = buflength;
+      count += bufleft;
+      refill();
+    }
+    else {
+      unsigned copylen = end - ptr;
+      out += mystring(ptr, copylen);
+      bufstart += copylen+1;
+      count += copylen+1;
+      break;
+    }
+  }
+  unlock();
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdibuf_netstring.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,41 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <string.h>
+#include "fdbuf.h"
+#include "mystring/mystring.h"
+
+bool fdibuf::getnetstring(mystring& out)
+{
+  // Read in the size
+  char ch;
+  unsigned long size = 0;
+  for(;;) {
+    if(!get(ch))
+      return false;
+    if(ch == ':')
+      break;
+    else if(ch >= '0' && ch <= '9')
+      size = size*10 + (ch-'0');
+    else
+      return false;
+  }
+  char tmp[size];
+  if(!read(tmp, size) || !get(ch) || ch != ',')
+    return false;
+  out = mystring(tmp, size);
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdobuf.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,209 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "fdbuf.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// Globals
+///////////////////////////////////////////////////////////////////////////////
+fdobuf fout(1);
+fdobuf ferr(2);
+
+///////////////////////////////////////////////////////////////////////////////
+// Class fdobuf
+///////////////////////////////////////////////////////////////////////////////
+fdobuf::fdobuf(int fdesc, bool dc, unsigned bufsz)
+  : fdbuf(fdesc, dc, bufsz),
+    bufpos(0)
+{
+}
+
+fdobuf::fdobuf(const char* filename, int f, int mode, unsigned bufsz)
+  : fdbuf(open(filename, O_WRONLY | f, mode), true, bufsz),
+    bufpos(0)
+{
+  if(fd == -1) {
+    flags = flag_error;
+    errnum = errno;
+  }
+}
+
+fdobuf::~fdobuf()
+{
+  flush();
+}
+
+bool fdobuf::close()
+{
+  if(!flush())
+    return false;
+  lock();
+  bool r = fdbuf::close();
+  unlock();
+  return r;
+}
+
+bool fdobuf::operator!() const
+{
+  return error() || closed();
+}
+
+bool fdobuf::nflush(bool withsync)
+{
+  if(flags)
+    return false;
+  while(bufstart < buflength) {
+    ssize_t written = ::write(fd, buf+bufstart, buflength-bufstart);
+    if(written == -1) {
+      flags |= flag_error;
+      errnum = errno;
+      return false;
+    }
+    else {
+      bufstart += written;
+      offset += written;
+    }
+  }
+  buflength = 0;
+  bufstart = 0;
+  bufpos = 0;
+  if(withsync && (fsync(fd) == -1)) {
+    flags |= flag_error;
+    errnum = errno;
+    return false;
+  }
+  return true;
+}
+
+bool fdobuf::flush()
+{
+  lock();
+  bool r = nflush(false);
+  unlock();
+  return r;
+}
+
+bool fdobuf::sync()
+{
+  lock();
+  bool r = nflush(true);
+  unlock();
+  return r;
+}
+
+bool fdobuf::write(char ch)
+{
+  if(flags)
+    return false;
+
+  lock();
+  count = 0;
+  buf[bufpos++] = ch;
+  //if(buflength >= bufsize && !nflush(false)) {
+  //  unlock();
+  //  return false;
+  //}
+  if(bufpos >= buflength)
+    buflength = bufpos;
+  if(buflength >= bufsize && !nflush(false)) {
+    unlock();
+    return false;
+  }
+  count = 1;
+  unlock();
+  return true;
+}
+
+bool fdobuf::write_large(const char* data, unsigned datalen)
+{
+  if(flags)
+    return false;
+
+  lock();
+  count = 0;
+
+  if(!nflush(false)) {
+    unlock();
+    return false;
+  }
+
+  while(datalen > 0) {
+    ssize_t written = ::write(fd, data, datalen);
+    if(written == -1) {
+      flags |= flag_error;
+      errnum = errno;
+      unlock();
+      return false;
+    }
+    datalen -= written;
+    data += written;
+    offset += written;
+    count += written;
+  }
+  unlock();
+  return true;
+}
+
+bool fdobuf::write(const char* data, unsigned datalen)
+{
+  if(datalen >= bufsize)
+    return write_large(data, datalen);
+  
+  if(flags)
+    return false;
+
+  lock();
+  const char* ptr = data;
+  count = 0;
+  // Amount is the number of bytes available in the buffer
+  unsigned amount = bufsize-bufpos;
+  while(datalen >= amount) {
+    // If we get here, this copy will completely fill the buffer,
+    // requiring a flush
+    memcpy(buf+bufpos, ptr, amount);
+    bufpos = bufsize;
+    buflength = bufsize;
+    datalen -= amount;
+    ptr += amount;
+    if(!nflush(false)) {
+      unlock();
+      return false;
+    }
+    count += amount;
+    amount = bufsize-bufpos;
+  }
+  // At this point, the remaining data will fit into the buffer
+  memcpy(buf+bufpos, ptr, datalen);
+  count += datalen;
+  bufpos += datalen;
+  if(bufpos > buflength) buflength = bufpos;
+  unlock();
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Manipulators
+///////////////////////////////////////////////////////////////////////////////
+fdobuf& endl(fdobuf& fd)
+{
+  fd.write("\n", 1);
+  fd.flush();
+  return fd;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdobuf.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,89 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef FDBUF__FDOBUF__H__
+#define FDBUF__FDOBUF__H__
+
+class fdobuf : protected fdbuf
+{
+public:
+  enum openflags { create=O_CREAT, 
+		   excl=O_EXCL,
+		   trunc=O_TRUNC,
+		   append=O_APPEND };
+
+  fdobuf(const char* filename, int, int mode = 0666,
+	 unsigned bufsz = FDBUF_SIZE);
+  fdobuf(int fdesc, bool dc=false, unsigned bufsz = FDBUF_SIZE);
+  virtual ~fdobuf();
+  bool close();
+  bool operator!() const;
+  operator bool() const
+    {
+      return !operator!();
+    }
+  bool flush();
+  bool sync();
+  virtual bool write(char);
+  bool write(unsigned char c) { return write((char)c); }
+  bool write(signed char c) { return write((char)c); }
+  virtual bool write(const char*, unsigned);
+  bool write(const unsigned char* b, unsigned l) { return write((char*)b, l); }
+  bool write(const signed char* b, unsigned l) { return write((char*)b, l); }
+  virtual bool write_large(const char*, unsigned);
+  unsigned last_count() { return count; }
+  bool seek(unsigned o);
+  bool rewind() { return seek(0); }
+  unsigned tell() const { return offset + bufpos; }
+
+  bool chown(uid_t, gid_t) const;
+  bool chmod(mode_t) const;
+  
+  fdobuf& operator<<(const char* str)
+    {
+      write(str, strlen(str));
+      return *this;
+    }
+  fdobuf& operator<<(char ch)
+    {
+      write(ch);
+      return *this;
+    }
+  fdobuf& operator<<(fdobuf& (*manip)(fdobuf&))
+    {
+      return manip(*this);
+    }
+  fdobuf& operator<<(unsigned long);
+  fdobuf& operator<<(signed long);
+  fdobuf& operator<<(unsigned i) { return operator<<((unsigned long)i); }
+  fdobuf& operator<<(signed i) { return operator<<((signed long)i); }
+  fdobuf& operator<<(unsigned short i) { return operator<<((unsigned long)i); }
+  fdobuf& operator<<(signed short i) { return operator<<((signed long)i); }
+
+  int error_number() const { return errnum; }
+protected:
+  virtual bool nflush(bool withsync);
+
+  unsigned bufpos;		// Current write position in the buffer
+  unsigned count;		// Number of bytes written by last operation
+};
+
+fdobuf& endl(fdobuf& fd);
+
+extern fdobuf fout;
+extern fdobuf ferr;
+
+#endif // FDBUF__FDOBUF__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdobuf_chownmod.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,34 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <string.h>
+#include "fdbuf.h"
+#include <sys/stat.h>
+#include <unistd.h>
+
+bool fdobuf::chown(uid_t uid, gid_t gid) const
+{
+  if(error())
+    return false;
+  return fchown(fd, uid, gid) != -1;
+}
+
+bool fdobuf::chmod(mode_t mode) const
+{
+  if(error())
+    return false;
+  return fchmod(fd, mode) != -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdobuf_seek.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,48 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "fdbuf.h"
+#include <errno.h>
+#include <unistd.h>
+
+bool fdobuf::seek(unsigned o)
+{
+  if(flags)
+    return false;
+
+  lock();
+  unsigned buf_start = offset;
+  unsigned buf_end = offset + buflength;
+  if(o >= buf_start && o < buf_end) {
+    bufpos = o - buf_start;
+  }
+  else {
+    if(!nflush(false)) {
+      unlock();
+      return false;
+    }
+    if(lseek(fd, o, SEEK_SET) != (off_t)o) {
+      errnum = errno;
+      flags |= flag_error;
+      unlock();
+      return false;
+    }
+    offset = o;
+  }
+  count = 0;
+  unlock();
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdobuf_signed.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,38 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "fdbuf.h"
+#include <limits.h>
+
+#define MAXSTRLEN ((sizeof(signed long)*CHAR_BIT)/3)
+
+fdobuf& fdobuf::operator<<(signed long i)
+{
+  if(i == 0)
+    return operator<<('0');
+  if(i < 0) {
+    operator<<('-');
+    i = -i;
+  }
+  char buf[MAXSTRLEN+1];
+  char* ptr = buf+MAXSTRLEN;
+  *ptr-- = 0;
+  while(i) {
+    *ptr-- = i % 10 + '0';
+    i /= 10;
+  }
+  return operator<<(ptr+1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fdbuf/fdobuf_unsigned.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,34 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "fdbuf.h"
+#include <limits.h>
+
+#define MAXSTRLEN ((sizeof(signed long)*CHAR_BIT)/3)
+
+fdobuf& fdobuf::operator<<(unsigned long i)
+{
+  if(i == 0)
+    return operator<<('0');
+  char buf[MAXSTRLEN+1];
+  char* ptr = buf+MAXSTRLEN;
+  *ptr-- = 0;
+  while(i) {
+    *ptr-- = i % 10 + '0';
+    i /= 10;
+  }
+  return operator<<(ptr+1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mergelib.sh	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,16 @@
+set -e
+archive="$1"
+shift
+tmpdir=".libmerge.$archive.$$.$RANDOM.$USER"
+mkdir "$tmpdir"
+cd "$tmpdir"
+trap 'cd ..; rm -rf "$tmpdir"' EXIT
+for input in "$@"; do
+	dir="`basename "$input"`"
+	mkdir "$dir"
+	cd "$dir"
+	ar x ../../"$input"
+	cd ..
+done
+ar rc ../"$archive" */*
+ranlib ../"$archive"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,44 @@
+noinst_LIBRARIES = libmisc.a
+INCLUDES = -I..
+EXTRA_DIST = autodelete.h debug.h hash_table.h krbauth.c stat_fns.h
+
+if KRB5
+KRB5_SRCS = krbauth.c
+else
+KRB5_SRCS =
+endif
+
+libmisc_a_SOURCES = $(KRB5_SRCS) \
+	crc32.h crc32.cc crc_hash.h \
+	exec.h exec.cc \
+	itoa.h itoa.cc \
+	keystrlist.cc \
+	list_table.h list_table.cc \
+	lookup.h \
+	lookup_baseuser.cc \
+	lookup_domain.cc \
+	maildir.h maildir.cc \
+	map_table.h map_table.cc \
+	md5.h md5.c \
+	md5-crypt.c \
+	passwdfn.h passwdfn.cc \
+	pwcrypt.h pwcrypt.cc \
+	pwentry.h pwentry.cc \
+	pwentry_auth.cc \
+	pwentry_export_env.cc \
+	pwentry_table.h pwentry_table.cc \
+	response.h response_write.cc response_message.cc response_read.cc \
+	server.h server.cc \
+	server_call0.cc \
+	server_call1.cc \
+	server_call2.cc \
+	server_call3.cc \
+	server_call4.cc \
+	server_call5.cc \
+	server_call6.cc \
+	strlist.h strlist.cc \
+	strlist_read.cc \
+	strlist_write.cc \
+	strtou.h strtou.c \
+	un.h \
+	utoa.h utoa.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,436 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libmisc.a
+INCLUDES = -I..
+EXTRA_DIST = autodelete.h debug.h hash_table.h krbauth.c stat_fns.h
+@KRB5_TRUE@KRB5_SRCS = krbauth.c
+@KRB5_FALSE@KRB5_SRCS = 
+
+libmisc_a_SOURCES = $(KRB5_SRCS) 	crc32.h crc32.cc crc_hash.h 	exec.h exec.cc 	itoa.h itoa.cc 	keystrlist.cc 	list_table.h list_table.cc 	lookup.h 	lookup_baseuser.cc 	lookup_domain.cc 	maildir.h maildir.cc 	map_table.h map_table.cc 	md5.h md5.c 	md5-crypt.c 	passwdfn.h passwdfn.cc 	pwcrypt.h pwcrypt.cc 	pwentry.h pwentry.cc 	pwentry_auth.cc 	pwentry_export_env.cc 	pwentry_table.h pwentry_table.cc 	response.h response_write.cc response_message.cc response_read.cc 	server.h server.cc 	server_call0.cc 	server_call1.cc 	server_call2.cc 	server_call3.cc 	server_call4.cc 	server_call5.cc 	server_call6.cc 	strlist.h strlist.cc 	strlist_read.cc 	strlist_write.cc 	strtou.h strtou.c 	un.h 	utoa.h utoa.cc
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libmisc_a_LIBADD = 
+@KRB5_TRUE@libmisc_a_OBJECTS =  krbauth.o crc32.o exec.o itoa.o \
+@KRB5_TRUE@keystrlist.o list_table.o lookup_baseuser.o lookup_domain.o \
+@KRB5_TRUE@maildir.o map_table.o md5.o md5-crypt.o passwdfn.o pwcrypt.o \
+@KRB5_TRUE@pwentry.o pwentry_auth.o pwentry_export_env.o \
+@KRB5_TRUE@pwentry_table.o response_write.o response_message.o \
+@KRB5_TRUE@response_read.o server.o server_call0.o server_call1.o \
+@KRB5_TRUE@server_call2.o server_call3.o server_call4.o server_call5.o \
+@KRB5_TRUE@server_call6.o strlist.o strlist_read.o strlist_write.o \
+@KRB5_TRUE@strtou.o utoa.o
+@KRB5_FALSE@libmisc_a_OBJECTS =  crc32.o exec.o itoa.o keystrlist.o \
+@KRB5_FALSE@list_table.o lookup_baseuser.o lookup_domain.o maildir.o \
+@KRB5_FALSE@map_table.o md5.o md5-crypt.o passwdfn.o pwcrypt.o \
+@KRB5_FALSE@pwentry.o pwentry_auth.o pwentry_export_env.o \
+@KRB5_FALSE@pwentry_table.o response_write.o response_message.o \
+@KRB5_FALSE@response_read.o server.o server_call0.o server_call1.o \
+@KRB5_FALSE@server_call2.o server_call3.o server_call4.o server_call5.o \
+@KRB5_FALSE@server_call6.o strlist.o strlist_read.o strlist_write.o \
+@KRB5_FALSE@strtou.o utoa.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libmisc_a_SOURCES)
+OBJECTS = $(libmisc_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/misc/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES)
+	-rm -f libmisc.a
+	$(AR) cru libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD)
+	$(RANLIB) libmisc.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/misc
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+crc32.o: crc32.cc crc32.h
+exec.o: exec.cc ../../config.h exec.h ../vpwentry/vpwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../config/configrc.h
+itoa.o: itoa.cc itoa.h
+keystrlist.o: keystrlist.cc ../../config.h strlist.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+list_table.o: list_table.cc ../../config.h list_table.h \
+	../misc/hash_table.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../misc/crc_hash.h \
+	../misc/crc32.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+lookup_baseuser.o: lookup_baseuser.cc ../../config.h lookup.h \
+	../misc/pwentry.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../config/configrc.h \
+	../misc/strlist.h pwentry.h pwentry_table.h
+lookup_domain.o: lookup_domain.cc ../../config.h lookup.h \
+	../misc/pwentry.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../config/configrc.h \
+	../misc/strlist.h list_table.h ../misc/hash_table.h \
+	../misc/crc_hash.h ../misc/crc32.h map_table.h
+maildir.o: maildir.cc ../../config.h maildir.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../ac/dirent.h stat_fns.h
+map_table.o: map_table.cc ../../config.h map_table.h \
+	../misc/hash_table.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../misc/crc_hash.h \
+	../misc/crc32.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+md5-crypt.o: md5-crypt.c md5.h
+md5.o: md5.c ../../config.h md5.h
+passwdfn.o: passwdfn.cc ../../config.h passwdfn.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../fdbuf/fdbuf.h ../fdbuf/fdibuf.h ../fdbuf/fdobuf.h stat_fns.h
+pwcrypt.o: pwcrypt.cc ../../config.h pwcrypt.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h md5.h
+pwentry.o: pwentry.cc ../../config.h ../config/configrc.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h pwentry.h
+pwentry_auth.o: pwentry_auth.cc ../../config.h pwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h \
+	pwcrypt.h
+pwentry_export_env.o: pwentry_export_env.cc ../../config.h pwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../config/configrc.h ../misc/strlist.h \
+	exec.h ../vpwentry/vpwentry.h
+pwentry_table.o: pwentry_table.cc ../../config.h pwentry_table.h \
+	../misc/pwentry.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../config/configrc.h \
+	../misc/strlist.h
+response_message.o: response_message.cc ../../config.h response.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+response_read.o: response_read.cc ../../config.h response.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+response_write.o: response_write.cc ../../config.h response.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+server.o: server.cc ../../config.h server.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/response.h ../config/configrc.h ../misc/strlist.h un.h \
+	debug.h
+server_call0.o: server_call0.cc ../../config.h server.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/response.h ../config/configrc.h \
+	../misc/strlist.h debug.h
+server_call1.o: server_call1.cc ../../config.h server.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/response.h ../config/configrc.h \
+	../misc/strlist.h debug.h
+server_call2.o: server_call2.cc ../../config.h server.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/response.h ../config/configrc.h \
+	../misc/strlist.h debug.h
+server_call3.o: server_call3.cc ../../config.h server.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/response.h ../config/configrc.h \
+	../misc/strlist.h debug.h
+server_call4.o: server_call4.cc ../../config.h server.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/response.h ../config/configrc.h \
+	../misc/strlist.h debug.h
+server_call5.o: server_call5.cc ../../config.h server.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/response.h ../config/configrc.h \
+	../misc/strlist.h debug.h
+server_call6.o: server_call6.cc ../../config.h server.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/response.h ../config/configrc.h \
+	../misc/strlist.h debug.h
+strlist.o: strlist.cc ../../config.h strlist.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h
+strlist_read.o: strlist_read.cc ../../config.h strlist.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+strlist_write.o: strlist_write.cc ../../config.h strlist.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+strtou.o: strtou.c ../../config.h
+utoa.o: utoa.cc ../../config.h utoa.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h
+vdomain.o: vdomain.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../fdbuf/fdbuf.h ../config/configrc.h strlist.h pwentry.h \
+	../vpw/vpwtable.h ../vpw/vpwentry.h response.h
+vdomain_chattr.o: vdomain_chattr.cc ../../config.h vdomain.h \
+	../mystring/mystring.h ../fdbuf/fdbuf.h ../config/configrc.h \
+	strlist.h pwentry.h ../vpw/vpwtable.h ../vpw/vpwentry.h \
+	response.h pwcrypt.h autodelete.h
+vdomain_deluser.o: vdomain_deluser.cc ../../config.h vdomain.h \
+	../mystring/mystring.h ../fdbuf/fdbuf.h ../config/configrc.h \
+	strlist.h pwentry.h ../vpw/vpwtable.h ../vpw/vpwentry.h \
+	response.h autodelete.h maildir.h
+vdomain_lookup.o: vdomain_lookup.cc ../../config.h vdomain.h \
+	../mystring/mystring.h ../fdbuf/fdbuf.h ../config/configrc.h \
+	strlist.h pwentry.h ../vpw/vpwtable.h ../vpw/vpwentry.h \
+	response.h autodelete.h
+vdomain_set.o: vdomain_set.cc ../../config.h vdomain.h \
+	../mystring/mystring.h ../fdbuf/fdbuf.h ../config/configrc.h \
+	strlist.h pwentry.h ../vpw/vpwtable.h ../vpw/vpwentry.h \
+	response.h maildir.h
+vdomain_userdir.o: vdomain_userdir.cc ../../config.h vdomain.h \
+	../mystring/mystring.h ../fdbuf/fdbuf.h ../config/configrc.h \
+	strlist.h pwentry.h ../vpw/vpwtable.h ../vpw/vpwentry.h \
+	response.h crc_hash.h crc32.h
+vdomain_validate.o: vdomain_validate.cc ../../config.h vdomain.h \
+	../mystring/mystring.h ../fdbuf/fdbuf.h ../config/configrc.h \
+	strlist.h pwentry.h ../vpw/vpwtable.h ../vpw/vpwentry.h \
+	response.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/autodelete.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,26 @@
+#ifndef VMAILMGR__AUTO_DELETE__H__
+#define VMAILMGR__AUTO_DELETE__H__
+
+#include <sys/types.h>
+
+template<class T>
+class autodelete 
+{
+private:
+  T* ptr;
+public:
+  autodelete() : ptr(0) { }
+  autodelete(T* p) : ptr(p) { }
+  ~autodelete() { if(ptr) delete ptr; }
+  operator T*&() { return ptr; }
+  operator const T*() const { return ptr; }
+  const T* operator=(T* p) { return ptr = p; }
+  T* operator->() { return ptr; }
+  const T* operator->() const { return ptr; }
+  T& operator[](size_t i) { return ptr[i]; }
+  const T& operator[](size_t i) const { return ptr[i]; }
+  bool operator!() const { return !ptr; }
+  operator bool() const { return ptr; }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/crc32.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,140 @@
+#include "crc32.h"
+
+/*
+ * updcrc derived from article Copyright (C) 1986 Stephen Satchell.
+ *  NOTE: First argument must be in range 0 to 255.
+ *        Second argument is referenced twice.
+ *
+ * Programmers may incorporate any or all code into their programs,
+ * giving proper credit within the source. Publication of the
+ * source routines is permitted so long as proper credit is given
+ * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
+ * Omen Technology.
+ */
+
+/* Use a type unsigned long int variable to store the crc value.
+ * Initialise the variable to 0xFFFFFFFF before running the crc routine.
+ * VERY IMPORTANT!!!! -> This routine was developed for data communications
+ * and returns the crc bytes in LOW to HIGH order, NOT byte reversed!
+ * To turn the valu into a 'normal' LONGINT, you must reverse the bytes!
+ * e.g.
+ *
+ *    FOR(c=1; c<=4; c++)                         (* reverse     *)
+ *       l = (l << 8) | (byte)crc;                (* the bytes   *)
+ *    (* l now contains the 'normalized' crc *)
+ */
+
+/* Copyright (C) 1986 Gary S. Brown.  You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ *
+ * First, the polynomial itself and its table of feedback terms.  The
+ * polynomial is
+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ * Note that we take it "backwards" and put the highest-order term in
+ * the lowest-order bit.  The X^32 term is "implied"; the LSB is the
+ * X^31 term, etc.  The X^0 term (usually shown as "+1") results in
+ * the MSB being 1.
+ *
+ * Note that the usual hardware shift register implementation, which
+ * is what we're using (we're merely optimizing it by doing eight-bit
+ * chunks at a time) shifts bits into the lowest-order term.  In our
+ * implementation, that means shifting towards the right.  Why do we
+ * do it this way?  Because the calculated CRC must be transmitted in
+ * order from highest-order term to lowest-order term.  UARTs transmit
+ * characters in order from LSB to MSB.  By storing the CRC this way,
+ * we hand it to the UART in the order low-byte to high-byte; the UART
+ * sends each low-bit to hight-bit; and the result is transmission bit
+ * by bit from highest- to lowest-order term without requiring any bit
+ * shuffling on our part.  Reception works similarly.
+ *
+ * The feedback terms table consists of 256, 32-bit entries.  Notes:
+ *
+ *     The table can be generated at runtime if desired; code to do so
+ *     is shown later.  It might not be obvious, but the feedback
+ *     terms simply represent the results of eight shift/xor opera-
+ *     tions for all combinations of data and CRC register values.
+ *
+ *     The values must be right-shifted by eight bits by the "updcrc"
+ *     logic; the shift must be unsigned (bring in zeroes).  On some
+ *     hardware you could probably optimize the shift in assembler by
+ *     using byte-swap instructions.
+ *     polynomial 0xedb88320
+ */
+
+const crc32_t crc32tab[] = { /* a table of 32-bit CRC feedback terms */
+0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
+0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
+0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
+0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
+0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
+0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
+0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
+0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
+0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
+0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
+0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
+0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
+0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
+0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
+0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
+0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
+0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
+0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
+0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
+0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
+0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
+0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
+0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
+0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
+0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
+0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
+0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
+0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
+0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
+0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
+0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
+0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
+0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
+0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
+0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
+0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
+0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
+0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
+0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
+0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
+0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
+0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
+0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
+0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
+0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
+0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
+0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
+0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
+0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
+0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
+0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
+0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
+};
+
+#ifdef __cplusplus
+crc32_t crc32_c::update (const unsigned char *s, int len)
+/* update running CRC calculation with contents of a buffer */
+{
+	register crc32_t a = val;
+	while(len-- > 0)
+		a = crc32_update (a, *s++);
+	return (val = a) ^ CRC32INIT;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/crc32.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,48 @@
+/*********************************** CRC32 ***********************************/
+
+/* Use a type crc32_t variable to store the crc value.
+ * Initialise the variable to CRC32INIT before running the crc routine.
+ * for more details see the CRC32.C file */
+
+#ifndef CRC32INIT
+#define CRC32INIT 0xFFFFFFFFL /* the initializer for the 32-bit CRC */
+
+typedef unsigned long crc32_t; /* the type of the 32-bit CRC */
+
+extern const crc32_t crc32tab[]; /* a table of 32-bit CRC feedback terms */
+
+#ifdef __cplusplus
+
+inline crc32_t crc32_update (const crc32_t crc, const unsigned char octet)
+{
+  return crc32tab [(unsigned char) crc ^ octet] ^ ((crc >> 8) & 0x00FFFFFFL);
+}
+
+class crc32_c
+{
+private:
+  crc32_t val;
+public:
+  inline crc32_c (const crc32_t v = 0L) : val (v ^ CRC32INIT) {}
+  inline void init () { val = CRC32INIT; }
+  inline operator crc32_t () const { return val ^ CRC32INIT; }
+  inline crc32_t operator = (const crc32_c &n) {
+    return (val = n.val) ^ CRC32INIT;
+  }
+  inline crc32_t operator = (const crc32_t &n) {
+    return val = n ^ CRC32INIT, n;
+  }
+  inline void update (const unsigned char octet) {
+    val = crc32_update (val, octet);
+  }
+  crc32_t update (const unsigned char *block, int len);
+  inline crc32_t update (const char* block, int len) {
+    return update((const unsigned char*)block, len);
+  }
+};
+#else
+#define crc32_update(crc32,octet) ( crc32 = crc32tab[(unsigned char)(crc32) ^ \
+        (unsigned char)(octet) ] ^ ( ((crc32)>>8) & 0x00FFFFFFL ) )
+#endif
+
+#endif CRC32INIT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/crc_hash.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,17 @@
+#ifndef CRC_HASH__H__
+#define CRC_HASH__H__
+
+#include "misc/crc32.h"
+
+class crc_hash
+{
+public:
+  unsigned operator()(const mystring& key) const
+    {
+      crc32_c crc;
+      crc.update(key.c_str(), key.length());
+      return crc;
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/debug.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,94 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef VMAILMGR__DEBUG__H__
+#define VMAILMGR__DEBUG__H__
+
+#define trace(X) trace2(this,X)
+#define traceptr(X,P) trace3(this,X " " #P "=",P)
+#define tracestr(X,P) trace4(this,X " " #P "=(",P)
+
+#ifdef TRACE
+
+#include <unistd.h>
+
+static inline const char* itoh(unsigned i)
+{
+  static char convert[17] = "0123456789abcdef";
+  static char buf[9];
+  for(unsigned j = 8; j > 0; ) {
+    --j;
+    buf[j] = convert[i & 0xf];
+    i >>= 4;
+  }
+  buf[8] = 0;
+  return buf;
+}
+
+static inline void trace2(const void* s, const char* x)
+{
+  write(2, itoh((unsigned)s), 8);
+  write(2, ": ", 2);
+  write(2, x, strlen(x));
+  write(2, "\n", 1);
+}
+
+static inline void trace3(const void* s, const char* x, const void* p)
+{
+  write(2, itoh((unsigned)s), 8);
+  write(2, ": ", 2);
+  write(2, x, strlen(x));
+  write(2, itoh((unsigned)p), 8);
+  write(2, "\n", 1);
+}
+
+static inline void trace4(const void* s, const char* x, const char* p)
+{
+  write(2, itoh((unsigned)s), 8);
+  write(2, ": ", 2);
+  write(2, x, strlen(x));
+  write(2, itoh((unsigned)p), 8);
+  write(2, ")'", 2);
+  write(2, p, strlen(p));
+  write(2, "'\n", 2);
+}
+
+#else
+#define trace2(X,P)
+#define trace3(T,X,P)
+#define trace4(T,X,P)
+#endif
+
+#ifdef DEBUG
+
+static inline void debug(const char* x)
+{
+  write(2, x, strlen(x));
+  write(2, "\n", 1);
+}
+
+static inline void fail(int code, const char* message)
+{
+  debug(message);
+  exit(code);
+}
+
+#else
+#define fail(X,Y) exit(X)
+#define debug(X)
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/exec.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,89 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "exec.h"
+#include "config/configrc.h"
+
+int presetenv(const char* prefix, const mystring& value)
+{
+  unsigned plen = strlen(prefix);
+  char* tmp = new char[plen+value.length()+1];
+  strcpy(tmp, prefix);
+  strcpy(tmp+plen, value.c_str());
+  return putenv(tmp);
+  
+  // Note that tmp is never freed.  This was done as a result of problems
+  // using putenv with glibc 2.1, where freeing the pointer passed to
+  // putenv appeared to cause garbage to enter the environment.
+  //mystring tmp = prefix + value;
+  //return putenv(tmp.c_str());
+}
+
+int execute_one(const char* args[])
+{
+  int pid = fork();
+  switch(pid) {
+  case -1:
+    return -1;
+  case 0:
+    execvp(args[0], (char**)args);
+    exit(127);
+  default:
+    for(;;) {
+      int status;
+      if(waitpid(pid, &status, 0) == -1) {
+	if(errno != EINTR)
+	  return -1;
+      } else {
+	if(WIFEXITED(status))
+	  return WEXITSTATUS(status);
+	else
+	  return -1;
+      }
+    }
+  }
+  return 0;
+}
+ 
+static int execute(const configuration* node, const mystring& name)
+{
+  if(node->parent) {
+    int i = execute(node->parent, name);
+    if(i || (node->parent->directory == node->directory))
+      return i;
+  }
+  mystring path = node->directory + "/" + name;
+  struct stat buf;
+  if(stat(path.c_str(), &buf) != -1 && buf.st_mode & 0111) {
+    const char* args[] = { path.c_str(), 0 };
+    return execute_one(args);
+  }
+  else
+    return 0;
+}
+  
+int execute(const mystring& name)
+{
+  int i = execute(config, name);
+  return (i == 99) ? 0 : i;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/exec.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,12 @@
+#ifndef VMAILMGR__EXEC__H__
+#define VMAILMGR__EXEC__H__
+
+#include "vpwentry/vpwentry.h"
+#include "misc/strlist.h"
+
+int presetenv(const char* prefix, const mystring& value);
+
+int execute_one(const char* args[]);
+int execute(const mystring& name);
+
+#endif // VMAILMGR__EXEC__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/hash_table.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,273 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef HASH_TABLE__H__
+#define HASH_TABLE__H__
+
+#include "mystring/mystring.h"
+
+struct hash_base
+{
+  const mystring key;
+  const unsigned hash;
+  hash_base(const mystring& k, unsigned h)
+    : key(k), hash(h)
+    {
+    }
+};
+
+template<class T>
+struct hash_node : public hash_base
+{
+  T data;
+  hash_node(const mystring& k, unsigned h, T d)
+    : hash_base(k, h), data(d)
+    {
+    }
+};
+
+template<class T>
+struct hash_ptr_node : public hash_base
+{
+  T* data;
+  hash_ptr_node(const mystring& k, unsigned h, T* d)
+    : hash_base(k, h), data(d)
+    {
+    }
+  ~hash_ptr_node()
+    {
+      if(data)
+	delete data;
+    }
+};
+
+static const unsigned hash_prime_list[] = {
+  53,         97,         193,       389,       769,
+  1543,       3079,       6151,      12289,     24593,
+  49157,      98317,      196613,    393241,    786433,
+  1572869,    3145739,    6291469,   12582917,  25165843,
+  50331653,   100663319,  201326611, 402653189, 805306457,
+  1610612741, 3221225473U, 4294967291U
+};
+  
+template<class TYPE, class NODE, class HASH>
+class hash_table_iterator;
+
+template<class TYPE, class NODE, class HASH>
+class hash_table
+{
+  friend class hash_table_iterator<TYPE,NODE,HASH>;
+  
+  TYPE dummy;
+  HASH hash;
+  NODE** table;
+  unsigned prime_index;
+  unsigned prime;
+  unsigned oversize;
+  unsigned _count;
+
+  unsigned rehash(unsigned h) const
+    {
+      return (h + 1) % prime;
+    }
+  
+  void alloc()
+    {
+      prime = hash_prime_list[prime_index];
+      oversize = prime*3/4;
+      table = new NODE*[prime];
+      for(unsigned i = 0; i < prime; i++)
+	table[i] = 0;
+      _count = 0;
+    }
+
+  void realloc(unsigned new_index)
+    {
+      //unsigned old_prime_index = prime_index;
+      unsigned old_prime = prime;
+      NODE** old_table = table;
+      prime_index = new_index;
+      alloc();
+      for(unsigned i = 0; i < old_prime; i++)
+	if(old_table[i])
+	  base_insert(old_table[i], true);
+    }
+
+  unsigned lookup(const mystring& key, unsigned hash) const
+    {
+      for(unsigned h = hash % prime; table[h]; h = rehash(h))
+	if(table[h]->hash == hash && table[h]->key == key)
+	  return h;
+      return prime;
+    }
+
+  unsigned lookup(const mystring& key) const
+    {
+      return lookup(key, hash(key));
+    }
+
+  bool base_insert(NODE* e, bool unique)
+    {
+      unsigned h;
+      for(h = e->hash % prime; table[h]; h = rehash(h)) {
+	if(table[h]->hash == e->hash &&
+	   table[h]->key == e->key) {
+	  if(unique)
+	    return false;
+	  else {
+	    delete table[h];
+	    --_count;
+	    break;
+	  }
+	}
+      }
+      table[h] = e;
+      ++_count;
+      return true;
+    }
+      
+public:
+  typedef hash_table_iterator<TYPE,NODE,HASH> iterator;
+  
+  hash_table()
+    : dummy(0), prime_index(0)
+    {
+      alloc();
+    }
+  
+  ~hash_table()
+    {
+      if(table) {
+	empty();
+	delete[] table;
+      }
+    }
+
+  void empty()
+    {
+      for(unsigned i = 0; i < prime; i++)
+	if(table[i]) {
+	  delete table[i];
+	  table[i] = 0;
+	}
+      _count = 0;
+    }
+
+  bool exists(const mystring& key) const
+    {
+      return lookup(key) >= prime;
+    }
+
+  const TYPE& operator[](const mystring& key) const
+    {
+      unsigned h = lookup(key);
+      return (h >= prime) ? dummy : table[h]->data;
+    }
+      
+  TYPE& operator[](const mystring& key)
+    {
+      unsigned h = lookup(key);
+      return (h >= prime) ? dummy : table[h]->data;
+    }
+      
+  unsigned count() const 
+    {
+      return _count;
+    }
+  
+  bool insert(const mystring& key, TYPE data)
+    {
+      NODE* e = new NODE(key, hash(key), data);
+      if(_count >= oversize)
+	realloc(prime_index+1);
+      return base_insert(e, true);
+    }
+  
+  bool set(const mystring& key, TYPE data)
+    {
+      NODE* e = new NODE(key, hash(key), data);
+      if(_count >= oversize)
+	realloc(prime_index+1);
+      return base_insert(e, false);
+    }
+
+  bool remove(const mystring& key, bool mustexist = false)
+    {
+      unsigned h = lookup(key);
+      if(h < prime) {
+	delete table[h];
+	table[h] = 0;
+	--_count;
+	return true;
+      }
+      else
+	return !mustexist;
+    }
+};
+
+// hash table iterator
+// usage: for(var.iterator i = var; !i; i++) use(*i);
+template<class TYPE, class NODE, class HASH>
+class hash_table_iterator
+{
+  hash_table<TYPE,NODE,HASH>& table;
+  unsigned index;
+  void next()
+    {
+      while(index < table.prime && !table.table[index])
+	++index;
+    }
+public:
+  hash_table_iterator(hash_table<TYPE,NODE,HASH>& t) : table(t), index(0)
+    {
+      next();
+    }
+  bool operator!() const
+    {
+      return index < table.prime;
+    }
+  bool at_end() const
+    {
+      return index >= table.prime;
+    }
+  void operator++() 
+    {
+      ++index;
+      next();
+    }
+  TYPE& operator*()
+    {
+      return table.table[index]->data;
+    }
+  const TYPE& operator*() const
+    {
+      return table.table[index]->data;
+    }
+};
+
+class hash_sample
+{
+public:
+  unsigned operator()(const mystring& str) const
+    {
+      unsigned h = 0;
+      for(unsigned i = 0; i < str.length(); i++)
+	h = (h << 1) ^ (unsigned)str[i];
+      return h;
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/itoa.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,41 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "itoa.h"
+
+const char* itoa(int val, int padding)
+{
+  if(padding > 29)
+    padding = 29;
+  static char buf[30];
+  char* ptr = buf+29;
+  bool neg = (val < 0);
+  if(neg) {
+    val = -val;
+    --padding;
+  }
+  *ptr-- = 0;
+  do {
+    *ptr-- = (val % 10) + '0';
+    val /= 10;
+    --padding;
+  } while(val);
+  for(; padding > 0; --padding)
+    *ptr-- = '0';
+  if(neg)
+    *ptr-- = '-';
+  return ++ptr;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/itoa.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#ifndef ITOA__H__
+#define ITOA__H__
+
+#ifdef __cplusplus
+extern "C" const char* itoa(int, int = 0);
+#else
+extern const char* itoa(int, int);
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/keystrlist.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,32 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "strlist.h"
+
+void keystrlist::set(const mystring& var, const mystring& val)
+{
+  mystring addstr = mystring::NUL + var + "=" + val;
+  const char* ptr = find(datastr, var, '=');
+  if(ptr) {
+    unsigned len = strlen(ptr);
+    unsigned offset = ptr - datastr.c_str();
+    datastr = datastr.left(offset - 2 - var.length()) + addstr +
+      datastr.right(offset + len);
+  }
+  else
+    datastr += addstr;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/krbauth.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,82 @@
+/*
+ * krbauth.c: Check a username/password pair against krb5 by temporarily
+ *            obtaining a short-lived ticket for the corresponding
+ *            principal. Returns 1 in case of successful verification,
+ *            0 otherwise.
+ *
+ * Nickolai Zeldovich <kolya@MIT.EDU>
+ *
+ */
+
+#include <stddef.h>
+#include <krb5.h>
+#include <com_err.h>
+#include <string.h>
+
+#define KRB5_LIFETIME 5
+
+int krbauth(char *user, char *pass) {
+
+ krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME };
+ krb5_context kcontext;
+ krb5_error_code code;
+ krb5_principal me;
+ krb5_principal server;
+ krb5_creds my_creds;
+ krb5_timestamp now;
+ char *client_name;
+
+ if((code=krb5_init_context (&kcontext))) {
+#ifdef DEBUG
+  com_err("krbauth", code, "while initializing krb5");
+#endif
+  return 0; }
+
+ if((code=krb5_timeofday(kcontext,&now))) {
+#ifdef DEBUG
+  com_err("krbauth", code, "while getting time of day");
+#endif
+  return 0; }
+
+ if((code=krb5_parse_name(kcontext, user, &me))) {
+#ifdef DEBUG
+  com_err("krbauth", code, "while parsing name %s", user);
+#endif
+  return 0; }
+
+ if((code=krb5_unparse_name(kcontext, me, &client_name))) {
+#ifdef DEBUG
+  com_err("krbauth", code, "when unparsing name");
+#endif
+  return 0; }
+
+ memset((char *)&my_creds, 0, sizeof(my_creds));
+ my_creds.client = me;
+ if((code=krb5_build_principal_ext(kcontext, &server,
+	krb5_princ_realm(kcontext, me)->length,
+	krb5_princ_realm(kcontext, me)->data,
+	tgtname.length, tgtname.data,
+	krb5_princ_realm(kcontext, me)->length,
+	krb5_princ_realm(kcontext, me)->data,
+	0))) {
+#ifdef DEBUG
+  com_err("krbauth", code, "while building server name");
+#endif
+  return 0; }
+
+ my_creds.server = server;
+ my_creds.times.starttime = 0;
+ my_creds.times.endtime = now + KRB5_LIFETIME;
+ if((code=krb5_get_in_tkt_with_password(kcontext, 0, 0,
+	NULL, NULL, pass, 0, &my_creds, 0))) {
+#ifdef DEBUG
+  if(code==KRB5KRB_AP_ERR_BAD_INTEGRITY)
+   com_err("krbauth", code, "incorrect password");
+  else
+   com_err("krbauth", code, "while getting initial credentials");
+#endif
+  return 0;
+ }
+
+ return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/list_table.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,36 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include "list_table.h"
+#include "fdbuf/fdbuf.h"
+
+list_table::list_table(const mystring& filename)
+  : valid(false)
+{
+  fdibuf in(filename.c_str());
+  if(!in)
+    return;
+  mystring buf;
+  while(in.getline(buf))
+    set(buf.rstrip(), true);
+  valid = true;
+}
+
+list_table::~list_table()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/list_table.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,20 @@
+#ifndef VMAILMGR__LIST_TABLE__H__
+#define VMAILMGR__LIST_TABLE__H__
+
+#include "misc/hash_table.h"
+#include "misc/crc_hash.h"
+#include "mystring/mystring.h"
+
+class list_table : public hash_table<bool,hash_node<bool>,crc_hash>
+{
+  bool valid;
+public:
+  list_table(const mystring& filename);
+  ~list_table();
+  bool operator!() const
+    {
+      return !valid;
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/lookup.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#ifndef VMAILMGR__LOOKUP__H__
+#define VMAILMGR__LOOKUP__H__
+
+#include "misc/pwentry.h"
+
+extern bool is_local(mystring);
+extern mystring find_virtual(mystring);
+extern bool lookup_baseuser(mystring fulluser, pwentry* &pw, mystring& virtname);
+
+#endif // VMAILMGR__LOOKUP__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/lookup_baseuser.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,37 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "lookup.h"
+#include "pwentry.h"
+#include "pwentry_table.h"
+
+bool lookup_baseuser(mystring fulluser, pwentry* &pw, mystring& virtname)
+{
+  pwentry_table pwtable;
+  if(!pwtable)
+    return false;
+  for(size_t i = fulluser.length(); i > 0; ) {
+    mystring base = fulluser.left(i);
+    pw = pwtable[base.lower()];
+    if(pw) {
+      virtname = fulluser.right(i+1);
+      return true;
+    }
+    for(--i; i > 0 && fulluser[i] != '-'; i--) ;
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/lookup_domain.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,48 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <limits.h>
+#include "lookup.h"
+#include "list_table.h"
+#include "map_table.h"
+#include "config/configrc.h"
+
+bool is_local(mystring domain)
+{
+  mystring tblname = config->qmail_root() + "/control/locals";
+  list_table tbl(tblname.c_str());
+  if(!tbl)
+    return false;
+  return tbl[domain];
+}
+
+mystring find_virtual(mystring domain)
+{
+  domain = domain.lower();
+  mystring tblname = config->qmail_root() + "/control/virtualdomains";
+  map_table tbl(tblname.c_str());
+  if(!tbl)
+    return "";
+  for(unsigned i = 0; i != UINT_MAX && i < domain.length();
+      i = domain.find_first('.', i+1)) {
+    mystring tmp = tbl[domain.c_str()+i];
+    if(!!tmp)
+      return tmp;
+  }
+  return "";
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/maildir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,93 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "maildir.h"
+#include <unistd.h>
+#include <string.h>
+#include "ac/dirent.h"
+#include "stat_fns.h"
+#include "mystring/mystring.h"
+
+static inline int rmdir(const mystring& n)
+{
+  return rmdir(n.c_str());
+}
+
+int mkdirp(const mystring& dirname, mode_t mode)
+{
+  if(is_dir(dirname.c_str()))
+    return 0;
+  int i = dirname.find_last('/');
+  if(i > 0) {
+    if(mkdirp(dirname.left(i), 0755))
+      return -1;
+  }
+  return mkdir(dirname.c_str(), mode);
+}
+
+bool make_maildir(const mystring& dirname)
+{
+  if(mkdirp(dirname, 0700))
+    return false;
+  mystring curdir = dirname + "/cur";
+  if(mkdir(curdir.c_str(), 0755)) {
+    rmdir(dirname);
+    return false;
+  }
+  mystring newdir = dirname + "/new";
+  if(mkdir(newdir.c_str(), 0755)) {
+    rmdir(curdir);
+    rmdir(dirname);
+    return false;
+  }
+  mystring tmpdir = dirname + "/tmp";
+  if(mkdir(tmpdir.c_str(), 0755)) {
+    rmdir(newdir);
+    rmdir(curdir);
+    rmdir(dirname);
+    return false;
+  }
+  return true;
+}
+
+bool delete_directory(const mystring& dirname)
+{
+  DIR* dir = opendir(dirname.c_str());
+  if(!dir)
+    return false;
+  while(dirent* entry = readdir(dir)) {
+    const char* name = entry->d_name;
+    if(name[0] == '.' &&
+       (NAMLEN(entry) == 1 ||
+	(name[1] == '.' && NAMLEN(entry) == 2)))
+      continue;
+    mystring fullname = dirname + "/";
+    fullname += mystring(name, NAMLEN(entry));
+    if(is_dir(fullname.c_str())) {
+      if(!delete_directory(fullname)) {
+	closedir(dir);
+	return false;
+      }
+    }
+    else if(unlink(fullname.c_str())) {
+      closedir(dir);
+      return false;
+    }
+  }
+  closedir(dir);
+  return !rmdir(dirname);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/maildir.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,11 @@
+#ifndef VMAILMGR__MAILDIR__H__
+#define VMAILMGR__MAILDIR__H__
+
+#include <sys/types.h>
+#include "mystring/mystring.h"
+
+int mkdirp(const mystring&, mode_t);
+bool make_maildir(const mystring&);
+bool delete_directory(const mystring&);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/map_table.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,41 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <string.h>
+#include "map_table.h"
+#include "fdbuf/fdbuf.h"
+
+map_table::map_table(const mystring& filename)
+  : valid(false)
+{
+  fdibuf in(filename.c_str());
+  if(!in)
+    return;
+  mystring buf;
+  while(in.getline(buf)) {
+    buf = buf.rstrip();
+    int mid = buf.find_first(':');
+    if(mid > 0)
+      set(buf.left(mid).lower(), buf.right(mid+1));
+  }
+  valid = true;
+}
+
+map_table::~map_table()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/map_table.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,20 @@
+#ifndef VMAILMGR__MAP_TABLE__H__
+#define VMAILMGR__MAP_TABLE__H__
+
+#include "misc/hash_table.h"
+#include "misc/crc_hash.h"
+#include "mystring/mystring.h"
+
+class map_table : public hash_table<mystring,hash_node<mystring>,crc_hash>
+{
+  bool valid;
+public:
+  map_table(const mystring& filename);
+  ~map_table();
+  bool operator!() const
+    {
+      return !valid;
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/md5-crypt.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,235 @@
+/* One way encryption based on MD5 sum.
+   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "md5.h"
+
+
+/* Define our magic string to mark salt for MD5 "encryption"
+   replacement.  This is meant to be the same as for other MD5 based
+   encryption implementations.  */
+static const char md5_salt_prefix[] = "$1$";
+
+/* Table with characters for base64 transformation.  */
+static const char b64t[64] =
+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+
+/* Prototypes for local functions.  */
+extern char *md5_crypt_r __P ((const char *key, const char *salt,
+			       char *buffer, int buflen));
+extern char *md5_crypt __P ((const char *key, const char *salt));
+
+
+#ifndef MAX
+#define MAX(X,Y) (((X)>(Y))?(X):(Y))
+#endif
+
+#ifndef MIN
+#define MIN(X,Y) (((X)>(Y))?(Y):(X))
+#endif
+
+/* This entry point is equivalent to the `crypt' function in Unix
+   libcs.  */
+char *
+md5_crypt_r (key, salt, buffer, buflen)
+     const char *key;
+     const char *salt;
+     char *buffer;
+     int buflen;
+{
+  unsigned char alt_result[16];
+  struct md5_ctx ctx;
+  struct md5_ctx alt_ctx;
+  size_t salt_len;
+  size_t key_len;
+  size_t cnt;
+  char *cp;
+
+  /* Find beginning of salt string.  The prefix should normally always
+     be present.  Just in case it is not.  */
+  if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
+    /* Skip salt prefix.  */
+    salt += sizeof (md5_salt_prefix) - 1;
+
+  salt_len = MIN (strcspn (salt, "$"), 8);
+  key_len = strlen (key);
+
+  /* Prepare for the real work.  */
+  md5_init_ctx (&ctx);
+
+  /* Add the key string.  */
+  md5_process_bytes (key, key_len, &ctx);
+
+  /* Because the SALT argument need not always have the salt prefix we
+     add it separately.  */
+  md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx);
+
+  /* The last part is the salt string.  This must be at most 8
+     characters and it ends at the first `$' character (for
+     compatibility which existing solutions).  */
+  md5_process_bytes (salt, salt_len, &ctx);
+
+
+  /* Compute alternate MD5 sum with input KEY, SALT, and KEY.  The
+     final result will be added to the first context.  */
+  md5_init_ctx (&alt_ctx);
+
+  /* Add key.  */
+  md5_process_bytes (key, key_len, &alt_ctx);
+
+  /* Add salt.  */
+  md5_process_bytes (salt, salt_len, &alt_ctx);
+
+  /* Add key again.  */
+  md5_process_bytes (key, key_len, &alt_ctx);
+
+  /* Now get result of this (16 bytes) and add it to the other
+     context.  */
+  md5_finish_ctx (&alt_ctx, alt_result);
+
+  /* Add for any character in the key one byte of the alternate sum.  */
+  for (cnt = key_len; cnt > 16; cnt -= 16)
+    md5_process_bytes (alt_result, 16, &ctx);
+  md5_process_bytes (alt_result, cnt, &ctx);
+
+  /* For the following code we need a NUL byte.  */
+  *alt_result = '\0';
+
+  /* The original implementation now does something weird: for every 1
+     bit in the key the first 0 is added to the buffer, for every 0
+     bit the first character of the key.  This does not seem to be
+     what was intended but we have to follow this to be compatible.  */
+  for (cnt = key_len; cnt > 0; cnt >>= 1)
+    md5_process_bytes ((cnt & 1) != 0 ? (const char *) alt_result : key, 1,
+		       &ctx);
+
+  /* Create intermediate result.  */
+  md5_finish_ctx (&ctx, alt_result);
+
+  /* Now comes another weirdness.  In fear of password crackers here
+     comes a quite long loop which just processes the output of the
+     previous round again.  We cannot ignore this here.  */
+  for (cnt = 0; cnt < 1000; ++cnt)
+    {
+      /* New context.  */
+      md5_init_ctx (&ctx);
+
+      /* Add key or last result.  */
+      if ((cnt & 1) != 0)
+	md5_process_bytes (key, key_len, &ctx);
+      else
+	md5_process_bytes (alt_result, 16, &ctx);
+
+      /* Add salt for numbers not divisible by 3.  */
+      if (cnt % 3 != 0)
+	md5_process_bytes (salt, salt_len, &ctx);
+
+      /* Add key for numbers not divisible by 7.  */
+      if (cnt % 7 != 0)
+	md5_process_bytes (key, key_len, &ctx);
+
+      /* Add key or last result.  */
+      if ((cnt & 1) != 0)
+	md5_process_bytes (alt_result, 16, &ctx);
+      else
+	md5_process_bytes (key, key_len, &ctx);
+
+      /* Create intermediate result.  */
+      md5_finish_ctx (&ctx, alt_result);
+    }
+
+  /* Now we can construct the result string.  It consists of three
+     parts.  */
+  strncpy (buffer, md5_salt_prefix, MAX (0, buflen));
+  buflen -= strlen (md5_salt_prefix);
+  cp = buffer + strlen (md5_salt_prefix);
+
+  strncpy (cp, salt, MIN ((size_t) buflen, salt_len));
+  buflen -= MIN ((size_t) buflen, salt_len);
+  cp += MIN ((size_t) buflen, salt_len);
+
+  if (buflen > 0)
+    {
+      *cp++ = '$';
+      --buflen;
+    }
+
+#define b64_from_24bit(B2, B1, B0, N)					      \
+  do {									      \
+    unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);			      \
+    int n = (N);							      \
+    while (n-- > 0 && buflen > 0)					      \
+      {									      \
+	*cp++ = b64t[w & 0x3f];						      \
+	--buflen;							      \
+	w >>= 6;							      \
+      }									      \
+  } while (0)
+
+
+  b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4);
+  b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4);
+  b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4);
+  b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4);
+  b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4);
+  b64_from_24bit (0, 0, alt_result[11], 2);
+  if (buflen <= 0)
+    {
+      errno = ERANGE;
+      buffer = NULL;
+    }
+  else
+    *cp = '\0';		/* Terminate the string.  */
+
+  /* Clear the buffer for the intermediate result so that people
+     attaching to processes or reading core dumps cannot get any
+     information.  */
+  memset (alt_result, '\0', sizeof (alt_result));
+
+  return buffer;
+}
+
+
+char *
+md5_crypt (key, salt)
+     const char *key;
+     const char *salt;
+{
+  /* We don't want to have an arbitrary limit in the size of the
+     password.  We can compute the size of the result in advance and
+     so we can prepare the buffer we pass to `md5_crypt_r'.  */
+  static char *buffer = NULL;
+  static int buflen = 0;
+  int needed = 3 + strlen (salt) + 1 + 26 + 1;
+
+  if (buflen < needed)
+    {
+      buflen = needed;
+      if ((buffer = realloc (buffer, buflen)) == NULL)
+	return NULL;
+    }
+
+  return md5_crypt_r (key, salt, buffer, buflen);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/md5.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,447 @@
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+   according to the definition of MD5 in RFC 1321 from April 1992.
+   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#include "md5.h"
+
+#ifdef _LIBC
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+# endif
+/* We need to keep the namespace clean so define the MD5 function
+   protected using leading __ and use weak aliases.  */
+# define md5_init_ctx __md5_init_ctx
+# define md5_process_block __md5_process_block
+# define md5_process_bytes __md5_process_bytes
+# define md5_finish_ctx __md5_finish_ctx
+# define md5_read_ctx __md5_read_ctx
+# define md5_stream __md5_stream
+# define md5_buffer __md5_buffer
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n)							\
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+void
+md5_init_ctx (ctx)
+     struct md5_ctx *ctx;
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_read_ctx (ctx, resbuf)
+     const struct md5_ctx *ctx;
+     void *resbuf;
+{
+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_finish_ctx (ctx, resbuf)
+     struct md5_ctx *ctx;
+     void *resbuf;
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+							(ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md5_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md5_stream (stream, resblock)
+     FILE *stream;
+     void *resblock;
+{
+  /* Important: BLOCKSIZE must be a multiple of 64.  */
+#define BLOCKSIZE 4096
+  struct md5_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+	 computation function processes the whole buffer so that with the
+	 next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      do
+	{
+	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+	  sum += n;
+	}
+      while (sum < BLOCKSIZE && n != 0);
+      if (n == 0 && ferror (stream))
+        return 1;
+
+      /* If end of file is reached, end the loop.  */
+      if (n == 0)
+	break;
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+			BLOCKSIZE % 64 == 0
+       */
+      md5_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+  /* Add the last bytes if necessary.  */
+  if (sum > 0)
+    md5_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md5_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+md5_buffer (buffer, len, resblock)
+     const char *buffer;
+     size_t len;
+     void *resblock;
+{
+  struct md5_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md5_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md5_finish_ctx (&ctx, resblock);
+}
+
+
+void
+md5_process_bytes (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (left_over + add > 64)
+	{
+	  md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
+	  /* The regions in the following copy operation cannot overlap.  */
+	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+		  (left_over + add) & 63);
+	  ctx->buflen = (left_over + add) & 63;
+	}
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len > 64)
+    {
+      md5_process_block (buffer, len & ~63, ctx);
+      buffer = (const char *) buffer + (len & ~63);
+      len &= 63;
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      memcpy (ctx->buffer, buffer, len);
+      ctx->buflen = len;
+    }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+md5_process_block (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
+{
+  md5_uint32 correct_words[16];
+  const md5_uint32 *words = buffer;
+  size_t nwords = len / sizeof (md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+  md5_uint32 A = ctx->A;
+  md5_uint32 B = ctx->B;
+  md5_uint32 C = ctx->C;
+  md5_uint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      md5_uint32 *cwp = correct_words;
+      md5_uint32 A_save = A;
+      md5_uint32 B_save = B;
+      md5_uint32 C_save = C;
+      md5_uint32 D_save = D;
+
+      /* First round: using the given function, the context and a constant
+	 the next context is computed.  Because the algorithms processing
+	 unit is a 32-bit word and it is determined to work on words in
+	 little endian byte order we perhaps have to change the byte order
+	 before the computation.  To reduce the work for the next steps
+	 we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)						\
+      do								\
+        {								\
+	  a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;		\
+	  ++words;							\
+	  CYCLIC (a, s);						\
+	  a += b;							\
+        }								\
+      while (0)
+
+      /* It is unfortunate that C does not provide an operator for
+	 cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+      /* Before we start, one word to the strange constants.
+	 They are defined in RFC 1321 as
+
+	 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+       */
+
+      /* Round 1.  */
+      OP (A, B, C, D,  7, 0xd76aa478);
+      OP (D, A, B, C, 12, 0xe8c7b756);
+      OP (C, D, A, B, 17, 0x242070db);
+      OP (B, C, D, A, 22, 0xc1bdceee);
+      OP (A, B, C, D,  7, 0xf57c0faf);
+      OP (D, A, B, C, 12, 0x4787c62a);
+      OP (C, D, A, B, 17, 0xa8304613);
+      OP (B, C, D, A, 22, 0xfd469501);
+      OP (A, B, C, D,  7, 0x698098d8);
+      OP (D, A, B, C, 12, 0x8b44f7af);
+      OP (C, D, A, B, 17, 0xffff5bb1);
+      OP (B, C, D, A, 22, 0x895cd7be);
+      OP (A, B, C, D,  7, 0x6b901122);
+      OP (D, A, B, C, 12, 0xfd987193);
+      OP (C, D, A, B, 17, 0xa679438e);
+      OP (B, C, D, A, 22, 0x49b40821);
+
+      /* For the second to fourth round we have the possibly swapped words
+	 in CORRECT_WORDS.  Redefine the macro to take an additional first
+	 argument specifying the function to use.  */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)					\
+      do 								\
+	{								\
+	  a += f (b, c, d) + correct_words[k] + T;			\
+	  CYCLIC (a, s);						\
+	  a += b;							\
+	}								\
+      while (0)
+
+      /* Round 2.  */
+      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+      OP (FG, D, A, B, C, 10,  9, 0x02441453);
+      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+      /* Round 3.  */
+      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+      /* Round 4.  */
+      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+      /* Add the starting values of the context.  */
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+}
+
+
+#ifdef _LIBC
+/* Define weak aliases.  */
+# undef md5_init_ctx
+weak_alias (__md5_init_ctx, md5_init_ctx)
+# undef md5_process_block
+weak_alias (__md5_process_block, md5_process_block)
+# undef md5_process_bytes
+weak_alias (__md5_process_bytes, md5_process_bytes)
+# undef md5_finish_ctx
+weak_alias (__md5_finish_ctx, md5_finish_ctx)
+# undef md5_read_ctx
+weak_alias (__md5_read_ctx, md5_read_ctx)
+# undef md5_stream
+weak_alias (__md5_stream, md5_stream)
+# undef md5_buffer
+weak_alias (__md5_buffer, md5_buffer)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/md5.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,156 @@
+/* Declaration of functions and data types used for MD5 sum computing
+   library functions.
+   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _MD5_H
+#define _MD5_H 1
+
+#include <stdio.h>
+
+#if defined HAVE_LIMITS_H || _LIBC
+# include <limits.h>
+#endif
+
+/* The following contortions are an attempt to use the C preprocessor
+   to determine an unsigned integral type that is 32 bits wide.  An
+   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+   doing that would require that the configure script compile and *run*
+   the resulting executable.  Locally running cross-compiled executables
+   is usually not possible.  */
+
+#ifdef _LIBC
+# include <sys/types.h>
+typedef u_int32_t md5_uint32;
+#else
+# if defined __STDC__ && __STDC__
+#  define UINT_MAX_32_BITS 4294967295U
+# else
+#  define UINT_MAX_32_BITS 0xFFFFFFFF
+# endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+   This should be valid for all systems GNU cares about because
+   that doesn't include 16-bit systems, and only modern systems
+   (that certainly have <limits.h>) have 64+-bit integral types.  */
+
+# ifndef UINT_MAX
+#  define UINT_MAX UINT_MAX_32_BITS
+# endif
+
+# if UINT_MAX == UINT_MAX_32_BITS
+   typedef unsigned int md5_uint32;
+# else
+#  if USHRT_MAX == UINT_MAX_32_BITS
+    typedef unsigned short md5_uint32;
+#  else
+#   if ULONG_MAX == UINT_MAX_32_BITS
+     typedef unsigned long md5_uint32;
+#   else
+     /* The following line is intended to evoke an error.
+        Using #error is not portable enough.  */
+     "Cannot determine unsigned 32-bit data type."
+#   endif
+#  endif
+# endif
+#endif
+
+#undef __P
+#if defined (__STDC__) && __STDC__
+# define __P(x) x
+#else
+# define __P(x) ()
+#endif
+
+/* Structure to save state of computation between the single steps.  */
+struct md5_ctx
+{
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+  char buffer[128];
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+extern void __md5_init_ctx __P ((struct md5_ctx *ctx));
+extern void md5_init_ctx __P ((struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void __md5_process_block __P ((const void *buffer, size_t len,
+				      struct md5_ctx *ctx));
+extern void md5_process_block __P ((const void *buffer, size_t len,
+				    struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void __md5_process_bytes __P ((const void *buffer, size_t len,
+				      struct md5_ctx *ctx));
+extern void md5_process_bytes __P ((const void *buffer, size_t len,
+				    struct md5_ctx *ctx));
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *__md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
+extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
+
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *__md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
+extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
+
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int __md5_stream __P ((FILE *stream, void *resblock));
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *__md5_buffer __P ((const char *buffer, size_t len,
+				void *resblock));
+extern void *md5_buffer __P ((const char *buffer, size_t len,
+			      void *resblock));
+
+#endif /* md5.h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/passwdfn.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,61 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "passwdfn.h"
+#include <pwd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "fdbuf/fdbuf.h"
+#include "mystring/mystring.h"
+#include "stat_fns.h"
+
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+static mystring getpasswd_interactive(const char* err)
+{
+  mystring pass1 = getpass("Enter the user's new password: ");
+  mystring pass2 = getpass("Please type it again for verification: ");
+  if(!(pass1 == pass2)) {
+    ferr << err << ": error: passwords don't match\n";
+    return "";
+  }
+  if(pass1.length() == 0)
+    ferr << err << ": error: password is empty.\n";
+  return pass1;
+}
+
+static mystring getpasswd_stdin(const char* err)
+{
+  mystring tmp;
+  fin.getline(tmp);
+  tmp = tmp.rstrip();
+  if(!tmp)
+    ferr << err << ": error: password is empty.\n";
+  return tmp;
+}
+
+mystring getpasswd(const char* err)
+{
+  return isatty(0) ?
+    getpasswd_interactive(err) :
+    getpasswd_stdin(err);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/passwdfn.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,8 @@
+#ifndef VMAILMGR__PASSWD_FN__H__
+#define VMAILMGR__PASSWD_FN__H__
+
+#include "mystring/mystring.h"
+
+mystring getpasswd(const char* program);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwcrypt.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,111 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#include "pwcrypt.h"
+
+#ifndef HAVE_CRYPT
+char *crypt(const char *key, const char *salt);
+#endif
+
+#ifndef HAVE_RANDOM
+long int random(void);
+#endif
+
+#ifdef USE_CRYPT
+
+static const char passwd_table[65] =
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+
+bool crypt_cmp(const mystring& pass, const mystring& stored)
+{
+  if(!stored || !pass)
+    return false;
+  const char* encrypted = crypt(pass.c_str(), stored.c_str());
+  return stored == encrypted;
+}
+
+const char* pwcrypt(const mystring& pass)
+{
+  char salt[2] = {
+    passwd_table[random() % 64],
+    passwd_table[random() % 64]
+  };
+  return crypt(pass.c_str(), salt);
+}
+
+#else // USE_CRYPT
+
+static const char passwd_table[65] =
+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+extern "C"
+{
+#include "md5.h"
+};
+
+static const char bin2hex_table[17] = "0123456789abcdef";
+
+#define OLD_MD5_CODE '3'
+
+static const char* encrypt_old_md5(const mystring& pass)
+{
+  md5_ctx ctx;
+  md5_init_ctx(&ctx);
+  md5_process_bytes(pass.c_str(), pass.length(), &ctx);
+  unsigned char md5[16];
+  md5_finish_ctx(&ctx, md5);
+  static char out[34];
+  out[0] = OLD_MD5_CODE;
+  for(unsigned i = 0; i < 16; i++) {
+    out[i*2+1] = bin2hex_table[md5[i]>>4];
+    out[i*2+2] = bin2hex_table[md5[i]&0xf];
+  }
+  out[33] = 0;
+  return out;
+}
+
+extern "C" char *md5_crypt __P ((const char *key, const char *salt));
+
+bool crypt_cmp(const mystring& pass, const mystring& stored)
+{
+  if(!stored || !pass)
+    return false;
+  const char* encrypted;
+  if(stored.length() == 33 && stored[0] == OLD_MD5_CODE)
+    encrypted = encrypt_old_md5(pass.c_str());
+  else if(stored[0] == '$' && stored[1] == '1' && stored[2] == '$')
+    encrypted = md5_crypt(pass.c_str(), stored.c_str());
+  else
+    encrypted = crypt(pass.c_str(), stored.c_str());
+  return stored == encrypted;
+}
+
+const char* pwcrypt(const mystring& pass)
+{
+  char salt[14] = "$1$";
+  for(unsigned i = 3; i < 11; i++)
+    salt[i] = passwd_table[random() % 64];
+  salt[12] = 0;
+  return md5_crypt(pass.c_str(), salt);
+}
+
+#endif // USE_MD5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwcrypt.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,9 @@
+#ifndef VMAILMGR__PWCRYPT__H__
+#define VMAILMGR__PWCRYPT__H__
+
+#include "mystring/mystring.h"
+
+bool crypt_cmp(const mystring& pass, const mystring& crypt);
+const char* pwcrypt(const mystring& pass);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwentry.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,50 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "config/configrc.h"
+#include "pwentry.h"
+
+pwentry::pwentry()
+  : name(getenv("USER")), pass(), uid(getuid()), gid(getgid()),
+    home(getenv("HOME")), config(::config, home + "/" LOCAL_CONFIG_DIR)
+{
+}
+
+pwentry::pwentry(const mystring& n, const mystring& p,
+		 uid_t u, gid_t g, const mystring& h)
+  : name(n), pass(p), uid(u), gid(g), home(h),
+    config(::config, home + "/" LOCAL_CONFIG_DIR)
+{
+}
+
+pwentry::pwentry(const struct passwd& pw)
+  : name(pw.pw_name), pass(pw.pw_passwd), uid(pw.pw_uid), gid(pw.pw_gid),
+    home(pw.pw_dir), config(::config, home + "/" LOCAL_CONFIG_DIR)
+{
+}
+
+pwentry::~pwentry()
+{
+}
+
+mystring pwentry::pwfile()
+{
+  return home + "/" + config.password_file();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwentry.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,46 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef VMAILMGR__PWENTRY__H__
+#define VMAILMGR__PWENTRY__H__
+
+#include <sys/types.h>
+#include "mystring/mystring.h"
+#include "config/configrc.h"
+
+struct pwentry
+{
+  mystring name;
+  mystring pass;
+  uid_t uid;
+  gid_t gid;
+  mystring home;
+  configuration config;
+  
+  pwentry();
+  pwentry(const mystring& n, const mystring& p,
+	  uid_t u, gid_t g, const mystring& h);
+  pwentry(const struct passwd&);
+  ~pwentry();
+  mystring pwfile();
+
+  bool authenticate(const mystring& phrase) const;
+  bool export_env() const;
+private:
+  pwentry(const pwentry&);	// Not implemented -- copying not permitted yet
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwentry_auth.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,30 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "pwentry.h"
+#include "pwcrypt.h"
+
+extern "C" int krbauth(const char*, const char*);
+
+bool pwentry::authenticate(const mystring& phrase) const
+{
+  return crypt_cmp(phrase, pass)
+#ifdef USE_KRB5
+    || krbauth(name.c_str(), phrase.c_str())
+#endif
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwentry_export_env.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,25 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "pwentry.h"
+#include "exec.h"
+
+bool pwentry::export_env() const
+{
+  return presetenv("USER=", name) == 0 &&
+    presetenv("HOME=", home) == 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwentry_table.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,74 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "pwentry_table.h"
+#include <pwd.h>
+#include <ctype.h>
+#include "config/configrc.h"
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+#if 0
+
+pwentry_table::pwentry_table()
+  : valid(false)
+{
+  setpwent();
+  const passwd* pw;
+  while((pw = getpwent()) != 0) {
+    for(char* ptr = pw->pw_name; *ptr != 0; ptr++)
+      if(isupper(*ptr))
+	*ptr = tolower(*ptr);
+    insert(pw->pw_name, new pwentry(pw->pw_name, pw->pw_passwd,
+				    pw->pw_uid, pw->pw_gid, pw->pw_dir));
+  }
+  endpwent();
+#ifdef HAVE_SHADOW_H
+  // Adjust all the users that have a shadow password
+  const spwd* spw;
+  setspent();
+  while((spw = getspent()) != 0) {
+    pwentry* pw = (*this)[spw->sp_namp];
+    if(pw)
+      pw->pass = spw->sp_pwdp;
+  }
+  endspent();
+#endif
+  valid = true;
+}
+
+pwentry_table::~pwentry_table()
+{
+}
+
+#else
+
+pwentry* pwentry_table::operator[](const mystring& name) const
+{
+  struct passwd* pw = getpwnam(name.c_str());
+  if(!pw)
+    return 0;
+#ifdef HAVE_SHADOW_H
+  struct spwd* spw = getspnam(name.c_str());
+  if(spw)
+    pw->pw_passwd = spw->sp_pwdp;
+#endif
+  return new pwentry(*pw);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/pwentry_table.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,34 @@
+#ifndef VMAILMGR__PWENTRY_TABLE__H__
+#define VMAILMGR__PWENTRY_TABLE__H__
+
+#include "misc/pwentry.h"
+
+#if 0
+
+#include "misc/hash_table.h"
+#include "misc/crc_hash.h"
+
+class pwentry_table : public hash_table<pwentry*,hash_ptr_node<pwentry>,crc_hash>
+{
+  bool valid;
+public:
+  pwentry_table();
+  ~pwentry_table();
+  bool operator!() const
+    {
+      return !valid;
+    }
+};
+
+#else
+
+class pwentry_table
+{
+public:
+  bool operator!() const { return false; }
+  pwentry* operator[](const mystring&) const;
+};
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/response.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,27 @@
+#ifndef VMAILMGR__RESPONSE__H__
+#define VMAILMGR__RESPONSE__H__
+
+#include "mystring/mystring.h"
+
+struct response
+{
+  enum response_code { ok=0, bad=1, err=2, econn=3 };
+  const response_code code;
+  const mystring msg;
+
+  response(response_code c, mystring m) : code(c), msg(m) { }
+  response(const response& r) : code(r.code), msg(r.msg) { }
+  ~response() { }
+
+  static response read(int fd);
+  bool write(int fd) const;
+  bool operator!() const { return code != ok; }
+  mystring message() const;
+  mystring codestr() const;
+
+  static const unsigned long maxsize = 1<<16-1;
+};
+
+#define RETURN(CODE,STR) return response(response::CODE, STR)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/response_message.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,39 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "response.h"
+
+mystring response::codestr() const
+{
+  static const mystring errstr = "ERROR";
+  static const mystring econnstr = "ECONN";
+  static const mystring badstr = "BAD";
+  static const mystring okstr = "OK";
+  static const mystring unknownstr = "???";
+  switch(code) {
+  case err: return errstr;
+  case econn: return econnstr;
+  case bad: return badstr;
+  case ok: return okstr;
+  default: return unknownstr;
+  }
+}
+
+mystring response::message() const
+{
+  return codestr() + ": " + msg;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/response_read.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,61 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <unistd.h>
+#include "response.h"
+
+static mystring receive_string(int fd)
+{
+  unsigned char lenbuf[2];
+  if(read(fd, lenbuf, 2) != 2)
+    return "";
+  ssize_t len = lenbuf[0] << 8 | lenbuf[1];
+  char buf[len+1];
+  if(read(fd, buf, len) != len)
+    return "";
+  return mystring(buf, len);
+}
+
+static response read_response(int fd)
+{
+  response::response_code code;
+  mystring msg;
+  unsigned char c;
+  if(read(fd, &c, 1) != 1) {
+    code = response::econn;
+    msg = "Sender aborted the data connection";
+  }
+  else {
+    msg = receive_string(fd);
+    switch(c) {
+    case 0:
+    case 1:
+    case 2:
+      code = (response::response_code)c;
+      break;
+    default:
+      code = response::econn;
+      msg = "Invalid data received from sender";
+    }
+  }
+  return response(code, msg);
+}
+
+response response::read(int fd)
+{
+  return read_response(fd);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/response_write.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,35 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "response.h"
+#include <unistd.h>
+#include <string.h>
+
+bool response::write(int fd) const
+{
+  if(msg.length() >= 1<<16)
+    return false;
+  ssize_t length = msg.length() + 3;
+  unsigned char buf[length];
+  buf[0] = (unsigned char)code;
+  buf[1] = msg.length() >> 8;
+  buf[2] = msg.length() & 0xff;
+  memcpy(buf+3, msg.c_str(), msg.length());
+  if(::write(fd, buf, length) != length)
+    return false;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,107 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "un.h"
+#include "debug.h"
+
+server_call::~server_call()
+{
+  trace("server_call::~server_call");
+  disconnect();
+  delete[] args;
+}
+
+static unsigned char* encode_string(unsigned char* ptr, mystring str)
+{
+  unsigned length = str.length();
+  *ptr++ = length >> 8;
+  *ptr++ = length & 0xff;
+  memcpy(ptr, str.c_str(), length);
+  return ptr+length;
+}
+
+mystring server_call::build_msg() const
+{
+  if(argc >= 1<<8)
+    return "";
+  unsigned msglen = 3 + cmd.length();
+  for(unsigned i = 0; i < argc; i++) {
+    if(args[i].length() >= 1<<16)
+      return "";
+    msglen += 2 + args[i].length();
+  }
+  char buf[msglen+3];
+  unsigned char* ptr = (unsigned char*)buf;
+  *ptr++ = 2;			// protocol ID
+  *ptr++ = msglen >> 8;
+  *ptr++ = msglen & 0xff;
+  *ptr++ = argc;
+  ptr = encode_string(ptr, cmd);
+  for(unsigned i = 0; i < argc; i++)
+    ptr = encode_string(ptr, args[i]);
+  return mystring(buf, msglen+3);
+}
+
+static bool send(int fd, mystring msg)
+{
+  ssize_t written = 0;
+  while(written < (ssize_t)msg.length()) {
+    ssize_t w = write(fd, msg.c_str()+written, msg.length()-written);
+    if(w == 0 || w == -1)
+      break;
+    written += w;
+  }
+  return written == (ssize_t)msg.length();
+}
+
+int server_call::connect(const mystring& socket_file) const
+{
+  int s = ::socket(AF_UNIX, SOCK_STREAM, 0);
+  if(s == -1)
+    return -1;
+  size_t size = sizeof(sockaddr_un) + socket_file.length()+1;
+  sockaddr_un* saddr = (sockaddr_un*)malloc(size);
+  saddr->sun_family = AF_UNIX;
+  strcpy(saddr->sun_path, socket_file.c_str());
+  if(::connect(s, (sockaddr*)saddr, SUN_LEN(saddr)) == -1)
+    return -1;
+  free(saddr);
+  return s;
+}
+
+void server_call::disconnect()
+{
+  if(fd >= 0)
+    close(fd);
+}
+
+response server_call::call(const mystring& socket_file)
+{
+  trace("server_call::call");
+  mystring msg = build_msg();
+  if(!msg)
+    RETURN(bad, "Invalid command data");
+  fd = connect(socket_file);
+  if(fd == -1)
+    RETURN(econn, "Unable to connect to the server");
+  if(!send(fd, msg))
+    RETURN(econn, "Server aborted the connection");
+  return response::read(fd);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,39 @@
+#ifndef VMAILMGR__SERVER__H__
+#define VMAILMGR__SERVER__H__
+
+#include "mystring/mystring.h"
+#include "misc/response.h"
+#include "config/configrc.h"
+
+class server_call
+{
+private:
+  mystring cmd;
+  unsigned argc;
+  mystring* args;
+  int fd;
+  
+  server_call();
+  server_call(const server_call&);
+  
+  mystring build_msg() const;
+  int connect(const mystring&) const;
+  void disconnect();
+  
+public:
+  server_call(mystring, unsigned a = 0);
+  server_call(mystring, mystring);
+  server_call(mystring, mystring, mystring);
+  server_call(mystring, mystring, mystring, mystring);
+  server_call(mystring, mystring, mystring, mystring, mystring);
+  server_call(mystring, mystring, mystring, mystring, mystring, mystring);
+  server_call(mystring, mystring, mystring, mystring, mystring, mystring,
+	      mystring);
+  ~server_call();
+  response call(const mystring& = config->socket_file());
+  void operand(int i, mystring m) { args[i] = m; }
+  mystring operand(int i) const { return args[i]; }
+  int socket() const { return fd; }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server_call0.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,27 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "debug.h"
+
+server_call::server_call(mystring c, unsigned a)
+  : cmd(c), argc(a), args(new mystring[a]), fd(-1)
+{
+  trace("server_call::server_call");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server_call1.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,28 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "debug.h"
+
+server_call::server_call(mystring c, mystring a0)
+  : cmd(c), argc(1), args(new mystring[1]), fd(-1)
+{
+  trace("server_call::server_call/2");
+  args[0] = a0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server_call2.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,31 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "debug.h"
+
+server_call::server_call(mystring c,
+			 mystring a0,
+			 mystring a1)
+  : cmd(c), argc(2), args(new mystring[2]), fd(-1)
+{
+  trace("server_call::server_call/3");
+  args[0] = a0;
+  args[1] = a1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server_call3.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,33 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "debug.h"
+
+server_call::server_call(mystring c,
+			 mystring a0,
+			 mystring a1,
+			 mystring a2)
+  : cmd(c), argc(3), args(new mystring[3]), fd(-1)
+{
+  trace("server_call::server_call/4");
+  args[0] = a0;
+  args[1] = a1;
+  args[2] = a2;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server_call4.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,36 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "debug.h"
+
+server_call::server_call(mystring c,
+			 mystring a0,
+			 mystring a1,
+			 mystring a2,
+			 mystring a3)
+  : cmd(c), argc(4), args(new mystring[4]), fd(-1)
+{
+  trace("server_call::server_call/5");
+  args[0] = a0;
+  args[1] = a1;
+  args[2] = a2;
+  args[3] = a3;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server_call5.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,37 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "debug.h"
+
+server_call::server_call(mystring c,
+			 mystring a0,
+			 mystring a1,
+			 mystring a2,
+			 mystring a3,
+			 mystring a4)
+  : cmd(c), argc(5), args(new mystring[5]), fd(-1)
+{
+  trace("server_call::server_call/6");
+  args[0] = a0;
+  args[1] = a1;
+  args[2] = a2;
+  args[3] = a3;
+  args[4] = a4;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/server_call6.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,39 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "server.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "debug.h"
+
+server_call::server_call(mystring c,
+			 mystring a0,
+			 mystring a1,
+			 mystring a2,
+			 mystring a3,
+			 mystring a4,
+			 mystring a5)
+  : cmd(c), argc(6), args(new mystring[6]), fd(-1)
+{
+  trace("server_call::server_call/6");
+  args[0] = a0;
+  args[1] = a1;
+  args[2] = a2;
+  args[3] = a3;
+  args[4] = a4;
+  args[5] = a5;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/stat_fns.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,31 @@
+#ifndef VMAILMGR__STAT_FNS__H__
+#define VMAILMGR__STAT_FNS__H__
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+inline bool is_exist(const char* filename)
+{
+  struct stat buf;
+  return !stat(filename, &buf);
+}
+
+inline bool is_dir(const char* filename)
+{
+  struct stat buf;
+  return !stat(filename, &buf) && S_ISDIR(buf.st_mode);
+}
+
+inline bool is_symlink(const char* filename)
+{
+  struct stat buf;
+  return !lstat(filename, &buf) && S_ISLNK(buf.st_mode);
+}
+
+inline bool is_file(const char* filename)
+{
+  struct stat buf;
+  return !stat(filename, &buf) && S_ISREG(buf.st_mode);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/strlist.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,54 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "strlist.h"
+
+static const char* compare(const char* ptr, const char* end,
+			   const mystring& var, char suffix)
+{
+  unsigned varlen = var.length();
+  unsigned ptrlen = (unsigned)(end-ptr);
+  if(ptrlen > varlen &&
+     !memcmp(var.c_str(), ptr, varlen) &&
+     (suffix && ptr[varlen] == suffix))
+    return ptr + varlen + (suffix ? 1 : 0);
+  return 0;
+}
+
+const char* strlist::find(const mystring& str, const mystring& var,
+			  char suffix)
+{
+  const char* ptr = str.c_str();
+  const char* end = ptr + str.length();
+  const char* tmp;
+  while(ptr < end) {
+    if((tmp = compare(ptr, end, var, suffix)) != 0)
+      return tmp;
+    ptr += strlen(ptr) + 1;
+  }
+  return 0;
+}
+
+mystring strlist::find(const mystring& var, char suffix) const
+{
+  return find(datastr, var, suffix);
+}
+
+void strlist::append(const mystring& str)
+{
+  datastr = datastr + mystring::NUL + str;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/strlist.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,47 @@
+#ifndef VMAILMGR__STR_LIST__H__
+#define VMAILMGR__STR_LIST__H__
+
+#include "mystring/mystring.h"
+
+class fdibuf;
+class fdobuf;
+
+class strlist 
+{
+protected:
+  mystring datastr;
+
+  static const char* find(const mystring& str, const mystring& var,
+			  char suffix);
+public:
+  strlist() { }
+  strlist(const mystring& d) : datastr(d) { }
+
+  mystring find(const mystring& prefix, char suffix = 0) const;
+  void append(const mystring& str);
+  
+  mystring str() const { return datastr; }
+
+  void operator=(const mystring& d) { datastr = d; }
+  bool operator!() const { return !datastr; }
+
+  bool read(const mystring&);
+  bool read(fdibuf&);
+
+  bool write(const mystring&) const;
+  bool write(fdobuf&) const;
+};
+
+class keystrlist : public strlist
+{
+public:
+  keystrlist() { }
+  keystrlist(const mystring& d) : strlist(d) { }
+
+  mystring get(const mystring& var) const { return find(var, '='); }
+  void set(const mystring& var, const mystring& val);
+
+  void operator=(const mystring& d) { datastr = d; }
+};
+
+#endif // VMAILMGR__STR_LIST__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/strlist_read.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,46 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "strlist.h"
+#include "fdbuf/fdbuf.h"
+
+bool strlist::read(const mystring& filename)
+{
+  fdibuf in(filename.c_str());
+  if(!in)
+    return false;
+  else
+    return read(in);
+}
+
+bool strlist::read(fdibuf& in)
+{
+  datastr = "";
+  mystring tmp;
+  bool first = true;
+  while(in.getline(tmp)) {
+    tmp = tmp.strip();
+    if(!tmp || tmp[0] == '#')
+      continue;
+    if(first)
+      first = false;
+    else
+      datastr += mystring::NUL;
+    datastr += tmp;
+  }
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/strlist_write.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,35 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "strlist.h"
+#include "fdbuf/fdbuf.h"
+
+bool strlist::write(const mystring& filename) const
+{
+  fdobuf out(filename.c_str(), fdobuf::create | fdobuf::trunc);
+  if(!out)
+    return false;
+  else
+    return write(out);
+}
+
+bool strlist::write(fdobuf& out) const
+{
+  for(mystring_iter iter(datastr, '\0'); iter; ++iter)
+    out << *iter << '\n';
+  return out;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/strtou.c	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,42 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <limits.h>
+
+unsigned strtou(const char* ptr, const char** endptr)
+{
+  unsigned uint = 0;
+  if(ptr) {
+    while(*ptr && isspace(*ptr))
+      ++ptr;
+    if(*ptr == '-') {
+      uint = UINT_MAX;
+      ++ptr;
+      while(isdigit(*ptr))
+	++ptr;
+    }
+    else {
+      uint = 0;
+      while(isdigit(*ptr))
+	uint = (uint * 10) + (*ptr++ - '0');
+    }
+  }
+  if(endptr)
+    *endptr = ptr;
+  return uint;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/strtou.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,14 @@
+#ifndef VMAILMGR__STRTOU__H__
+#define VMAILMGR__STRTOU__H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned strtou(const char* ptr, const char** endptr);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/un.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,13 @@
+#ifndef VMAILMGR__UN__H__
+#define VMAILMGR__UN__H__
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef SUN_LEN
+/* Evaluate to actual length of the `sockaddr_un' structure.  */
+#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path)	      \
+		      + strlen ((ptr)->sun_path))
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/utoa.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,40 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <limits.h>
+#include "utoa.h"
+
+static const mystring dash = "-";
+static const mystring zero = "0";
+
+mystring utoa(unsigned u)
+{
+  if(!u)
+    return zero;
+  else if(u == UINT_MAX)
+    return dash;
+  else {
+    char buf[30];
+    char* ptr = buf+29;
+    *ptr-- = 0;
+    while(u) {
+      *ptr-- = (u%10) + '0';
+      u /= 10;
+    }
+    return ptr+1;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/misc/utoa.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,8 @@
+#ifndef VMAILMGR__UTOA__H__
+#define VMAILMGR__UTOA__H__
+
+#include "mystring/mystring.h"
+
+extern mystring utoa(unsigned u);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/ChangeLog	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,116 @@
+2000-04-09  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* count.cc (count): Added this routine to count the number of
+	instances of a single character in a string.
+
+2000-04-06  Bruce Guenter  <bguenter@bguenter.pointsnorth.com>
+
+	* fdobuf.cc (operator<<): Moved this routine out of an inline
+	declaration.
+
+	* iter.h: Moved the mystring_iter declarations into this file.
+
+	* rep.h: Moved the mystringrep declarations into this file.
+
+	* join.h: Moved the mystringjoin declarations into this file.
+
+	* mystring.h (class mystring): Renamed the "find_first" and
+	"find_last" routines that scan for items in a set to
+	"find_first_of" and "find_last_of".
+
+1999-08-15  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* mystring.h (class mystring_iter): Changed the default seperator
+	for strings to '\0'
+	(class mystring): Added a NUL constant (single 0 byte string).
+
+1999-07-26  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* mystring.h (class mystring_iter): Added this new iterator class,
+	taken from code used in vmailmgr.  It is used to iterate over
+	essentially a token-delimited string.
+
+1999-07-14  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* Removed all vestiges of mystringtmp support from this library.
+
+1999-07-13  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* append.cc: Fixed same bug as below in append.
+
+	* assign.cc: Fixed bug in assign and dup where NULL pointers
+	caused a crash.
+
+	* append.cc, assign.cc: removed the mystringtmp versions of the
+	append, assign, and dup operations.  mystringtmp now only exists
+	in the cons[2-7].cc files and tmp.cc
+
+	* find.cc: Split this file into find_first, find_first_of,
+	find_last, and find_last_of.
+
+1999-07-12  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* join.cc (traverse): This routine traverses the linked list and
+	builds a mystringrep out of it.
+
+	* mystring.h: Renamed TRACE to MYSTRING_TRACE.
+	Added a new mystringjoin class.  This class is used to turn a list
+	of calls to "operator+" into a single constructor by building a
+	linked list on the stack.  This will replace mystringtmp.
+
+	* rep.cc (struct _rep_stats): Fixed the percentage function to not
+	do divide-by-zero; modified the "slack" reporting to report a
+	percentage of the requested length.
+
+	* assign.cc: Re-added dup and assign functions for "char*" type,
+	moving the constructors and assignment operators inline.
+
+	* append.cc: Re-added append functions for "char*" type.
+
+1999-07-08  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* mystring.h (class mystring): Eliminated the "mystring" return
+	value for the assign and append operators, since this return value
+	is never used and causes extra operations.
+
+	* operator_plus.cc: Created this new file containing the
+	"operator+" routine.
+
+	* operator_pleq.cc: Created this new file containing all the
+	"operator+=" routines.
+
+	* assign.cc: Created this new file containing all the assign and
+	dup primitives.
+
+	* mystring.h (class mystring): Removed the += operator taking
+	"mystringtmp" parameter, and replaced it with two routines, one
+	for "const mystring&", and one for "const char*".  This results in
+	a net code shrinkage.
+
+	* rep.cc (struct _rep_stats): Added this optional statistics
+	gathering class to determine the effectiveness of the slack space
+	and string appending.
+
+	* append.cc (append): Use the new rep->append routine.
+
+	* rep.cc (alloc): Allocate an amount of "slack" space when
+	allocating a string, to allow for later appends.
+	(append): This new routine appends a string to the current rep if
+	and only if the current rep has a single reference and the new
+	length of the string will fit within the current size.  If not, it
+	makes a dup of this+str and returns a pointer to it.
+
+1999-06-07  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* tmp.cc: Removed the contents of checkstr, and moved the
+	necessary parts into the constructors.  This makes the code more
+	efficient, as the constructors are adequately specific to omit
+	some of the branches in the comparisons.  It also ensures that len
+	is always initialized, allowing many of the simple functions to be
+	moved inline to the header file.
+
+1999-04-01  Bruce Guenter  <bguenter@mikhail.qcc.sk.ca>
+
+	* cons7.cc (mystring): Wrote this constructor to build a string
+	from 7 inputs.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,25 @@
+noinst_LIBRARIES = libmystring.a
+EXTRA_DIST = ChangeLog iter.h join.h mystring.h rep.h trace.h
+
+INCLUDES = -I..
+
+libmystring_a_SOURCES = \
+	append.cc \
+	assign.cc \
+	count.cc \
+	fdobuf.cc \
+	find_first_ch.cc \
+	find_first_of.cc \
+	find_last_ch.cc \
+	find_last_of.cc \
+	iter.cc \
+	join.cc \
+	lower.cc \
+	lstrip.cc \
+	mystring.cc \
+	rep.cc \
+	rstrip.cc \
+	sub.cc \
+	subst.cc \
+	strip.cc \
+	upper.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,323 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libmystring.a
+EXTRA_DIST = ChangeLog iter.h join.h mystring.h rep.h trace.h
+
+INCLUDES = -I..
+
+libmystring_a_SOURCES =  	append.cc 	assign.cc 	count.cc 	fdobuf.cc 	find_first_ch.cc 	find_first_of.cc 	find_last_ch.cc 	find_last_of.cc 	iter.cc 	join.cc 	lower.cc 	lstrip.cc 	mystring.cc 	rep.cc 	rstrip.cc 	sub.cc 	subst.cc 	strip.cc 	upper.cc
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libmystring_a_LIBADD = 
+libmystring_a_OBJECTS =  append.o assign.o count.o fdobuf.o \
+find_first_ch.o find_first_of.o find_last_ch.o find_last_of.o iter.o \
+join.o lower.o lstrip.o mystring.o rep.o rstrip.o sub.o subst.o strip.o \
+upper.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  ChangeLog Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libmystring_a_SOURCES)
+OBJECTS = $(libmystring_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/mystring/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libmystring.a: $(libmystring_a_OBJECTS) $(libmystring_a_DEPENDENCIES)
+	-rm -f libmystring.a
+	$(AR) cru libmystring.a $(libmystring_a_OBJECTS) $(libmystring_a_LIBADD)
+	$(RANLIB) libmystring.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/mystring
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+append.o: append.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h trace.h
+assign.o: assign.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h trace.h
+count.o: count.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+fdobuf.o: fdobuf.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../fdbuf/fdbuf.h ../../config.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+find_first_ch.o: find_first_ch.cc mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h
+find_first_of.o: find_first_of.cc mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h
+find_last_ch.o: find_last_ch.cc mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h
+find_last_of.o: find_last_of.cc mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h
+iter.o: iter.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+join.o: join.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+lower.o: lower.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+lstrip.o: lstrip.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+mystring.o: mystring.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h trace.h
+rep.o: rep.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h trace.h
+rstrip.o: rstrip.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+strip.o: strip.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+sub.o: sub.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+subst.o: subst.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+upper.o: upper.cc mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/append.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,18 @@
+#include "mystring.h"
+#include "trace.h"
+
+void mystring::append(const char* str, size_t len)
+{
+  if(!str || !len)
+    return;
+  if(!*this)
+    assign(str, len);
+  else
+    rep = rep->append(str, len);
+}
+
+void mystring::append(const char* in)
+{
+  if(in)
+    append(in, strlen(in));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/assign.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,55 @@
+#include "mystring.h"
+#include "trace.h"
+#include <ctype.h>
+#include <string.h>
+
+void mystring::dupnil()
+{
+  trace("");
+  rep = &nil;
+  rep->attach();
+}
+
+void mystring::assign(const char* in)
+{
+  if(in)
+    assign(in, strlen(in));
+  else {
+    mystringrep* tmp = rep;
+    dupnil();
+    tmp->detach();
+  }
+}
+
+void mystring::assign(const char* in, size_t len)
+{
+  trace("in='" << in << "'");
+  if(in != rep->buf) {
+    mystringrep* tmp = rep;
+    dup(in, len);
+    tmp->detach();
+  }
+}
+
+void mystring::dup(const char* in, size_t len)
+{
+  trace("in='" << in << "'");
+  rep = mystringrep::dup(in, len);
+  rep->attach();
+}
+
+void mystring::dup(const char* in)
+{
+  if(in)
+    dup(in, strlen(in));
+  else
+    dupnil();
+}
+
+void mystring::operator=(const mystringjoin& in)
+{
+  mystringrep* tmp = rep;
+  rep = in.traverse();
+  rep->attach();
+  tmp->detach();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/count.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,25 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "mystring.h"
+
+unsigned mystring::count(char ch) const
+{
+  unsigned c = 0;
+  for(int pos = find_first(ch); pos > 0; pos = find_first(ch, pos+1))
+    ++c;
+  return c;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/fdobuf.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,9 @@
+#include "mystring.h"
+#include "fdbuf/fdbuf.h"
+
+fdobuf& operator<<(fdobuf& out, const mystring& str)
+{
+  out.write(str.c_str(), str.length());
+  return out;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/find_first_ch.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,11 @@
+#include "mystring.h"
+#include <string.h>
+
+int mystring::find_first(char ch, size_t offset) const
+{
+  if(offset >= rep->length)
+    return -1;
+  char* ptr = strchr(rep->buf+offset, ch);
+  return ptr ? ptr-rep->buf : -1;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/find_first_of.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,22 @@
+#include "mystring.h"
+#include <string.h>
+
+int mystring::find_first_of(const char* setstr, size_t setlen,
+			    size_t offset) const
+{
+  for(; offset < rep->length; offset++) {
+    if(memchr(setstr, rep->buf[offset], setlen))
+      return offset;
+  }
+  return -1;
+}
+
+int mystring::find_first_of(const char* setstr, size_t offset) const
+{
+  return find_first_of(setstr, strlen(setstr), offset);
+}
+
+int mystring::find_first_of(const mystring& setstr, size_t offset) const
+{
+  return find_first_of(setstr.rep->buf, setstr.rep->length, offset);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/find_last_ch.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,14 @@
+#include "mystring.h"
+
+int mystring::find_last(char ch, size_t offset) const
+{
+  if(offset == (size_t)-1)
+    offset = rep->length-1;
+  const char* ptr = rep->buf + offset;
+  while(ptr >= rep->buf) {
+    if(*ptr == ch)
+      return ptr - rep->buf;
+    --ptr;
+  }
+  return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/find_last_of.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,24 @@
+#include "mystring.h"
+#include <string.h>
+
+int mystring::find_last_of(const char* setstr, size_t setlen,
+			   size_t offset) const
+{
+  if(offset == (size_t)-1)
+    offset = rep->length-1;
+  for(int i = offset; i >= 0; --i) {
+    if(memchr(setstr, rep->buf[i], setlen))
+      return i;
+  }
+  return -1;
+}
+
+int mystring::find_last_of(const char* setstr, size_t offset) const
+{
+  return find_last_of(setstr, strlen(setstr), offset);
+}
+
+int mystring::find_last_of(const mystring& setstr, size_t offset) const
+{
+  return find_last_of(setstr.rep->buf, setstr.rep->length, offset);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/iter.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,48 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "mystring.h"
+
+mystring_iter::mystring_iter(const mystring& s, char e)
+  : str(s), sep(e), pos(0)
+{
+  advance();
+}
+
+mystring_iter::~mystring_iter()
+{
+}
+
+void mystring_iter::advance()
+{
+  if(pos == -1)
+    return;
+  int i = str.find_first(sep, pos);
+  if(i == -1) {
+    if(pos >= 0 && pos < (int)str.length()) {
+      part = str.right(pos);
+      pos = str.length();
+    }
+    else {
+      part = "";
+      pos = -1;
+    }
+  }
+  else {
+    part = str.sub(pos, i-pos);
+    pos = i + 1;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/iter.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,38 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef MYSTRING__ITER__H__
+#define MYSTRING__ITER__H__
+
+class mystring_iter
+{
+  const mystring str;
+  const char sep;
+  int pos;
+  mystring part;
+
+  void advance();
+public:
+  mystring_iter(const mystring&, char = '\0');
+  ~mystring_iter();
+  
+  operator bool() const { return pos >= 0; }
+  bool operator!() const { return pos < 0; }
+  mystring operator*() const { return part; }
+  void operator++() { advance(); }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/join.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,61 @@
+#include "mystring.h"
+#include <string.h>
+
+// This "join" class relies on one fairly obscure detail in the C++
+// standard: temporaries are destructed only after the entire
+// "full-expression" has completed.  That is, if the sequence:
+// f(f(f(x))) creates three temporary objects, the inner objects are
+// destroyed only after the execution has completed.  This allows us
+// to build a complete linked-list on the stack.  Tricky, but efficient!
+
+struct tmpitem
+{
+  const char* str;
+  unsigned len;
+};
+
+mystringrep* mystringjoin::traverse() const
+{
+  // At first glance, a recursive implementation would be the most logical
+  // way of doing this, but it turned out to be a significant loss.  This
+  // method traverses the pointer chain to first determine the length, and
+  // then to do the actual copying.
+
+  // Note the use of do/while loops to avoid a test at the head of the loop
+  // which will always succeed (there is always at least one node or item).
+  unsigned count = 0;
+  const mystringjoin* node = this;
+  do {
+    ++count;
+  } while((node = node->prev) != 0);
+
+  // The use of a temporary array avoids re-traversing the pointer
+  // chain, which is a slight performance win.
+  tmpitem items[count];
+  
+  unsigned length = 0;
+  node = this;
+  tmpitem* item = items;
+  do {
+    unsigned l = node->rep ? node->rep->length : strlen(node->str);
+    length += l;
+    item->str = node->str;
+    item->len = l;
+    ++item;
+  } while((node = node->prev) != 0);
+
+  // Since the chain is constructed such that the last item is the
+  // first node, the string gets constructed in reverse order.
+  mystringrep* rep = mystringrep::alloc(length);
+  char* buf = rep->buf + length;
+  item = items;
+  do {
+    unsigned l = item->len;
+    buf -= l;
+    memcpy(buf, item->str, l);
+    ++item;
+  } while(--count != 0);
+
+  rep->buf[length] = 0;
+  return rep;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/join.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,75 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef MYSTRING__JOIN__H__
+#define MYSTRING__JOIN__H__
+
+class mystringjoin
+{
+private:
+  const mystringjoin* prev;
+  mystringrep* rep;
+  const char* str;
+
+  mystringjoin();
+public:
+  mystringjoin(const mystringjoin& j)
+    : prev(j.prev), rep(j.rep), str(j.str)
+    {
+      rep->attach();
+    }
+  mystringjoin(const mystring& s)
+    : prev(0), rep(s.rep), str(s.rep->buf)
+    {
+      rep->attach();
+    }
+  mystringjoin(const char* s)
+    : prev(0), rep(0), str(s)
+    {
+    }
+  mystringjoin(const mystringjoin& p, const mystring& s)
+    : prev(&p), rep(s.rep), str(s.rep->buf)
+    {
+      rep->attach();
+    }
+  mystringjoin(const mystringjoin& p, const char* s)
+    : prev(&p), rep(0), str(s)
+    {
+    }
+  ~mystringjoin()
+    {
+      if(rep) rep->detach();
+    }
+  mystringrep* traverse() const;
+};
+
+inline mystring::mystring(const mystringjoin& j)
+  : rep(j.traverse())
+{
+  rep->attach();
+}
+
+inline mystringjoin operator+(const mystringjoin& a, const mystring& b)
+{
+  return mystringjoin(a, b);
+}
+
+inline mystringjoin operator+(const mystringjoin& a, const char* b)
+{
+  return mystringjoin(a, b);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/lower.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,19 @@
+#include "mystring.h"
+#include <ctype.h>
+
+mystring mystring::lower() const
+{
+  const unsigned length = rep->length;
+  char buf[length+1];
+  const char* in = rep->buf + length;
+  bool changed = false;
+  for(char* out = buf+length; out >= buf; in--, out--)
+    if(isupper(*in))
+      *out = tolower(*in), changed = true;
+    else
+      *out = *in;
+  if(!changed)
+    return *this;
+  else
+    return mystring(buf, length);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/lstrip.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "mystring.h"
+#include <ctype.h>
+
+mystring mystring::lstrip() const
+{
+  const char* ptr = rep->buf;
+  while(*ptr && isspace(*ptr))
+    ++ptr;
+  return ptr;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/mystring.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,28 @@
+#include "mystring.h"
+#include "trace.h"
+#include <ctype.h>
+#include <string.h>
+
+#ifdef MYSTRING_TRACE
+mystring::~mystring()
+{
+  trace("rep=" << (void*)rep);
+  rep->detach();
+}
+#endif
+
+int mystring::operator!=(const char* in) const
+{
+  if(rep->buf == in)
+    return 0;
+  return strcmp(rep->buf, in);
+}
+
+int mystring::operator!=(const mystring& in) const
+{
+  if(rep->buf == in.rep->buf)
+    return 0;
+  return strcmp(rep->buf, in.rep->buf);
+}
+
+const mystring mystring::NUL("", 1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/mystring.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,125 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef MYSTRING__H__
+#define MYSTRING__H__
+
+#include <sys/types.h>
+#include "mystring/rep.h"
+
+class mystringjoin;
+class mystring
+{
+  friend class mystringtmp;
+  friend class mystringjoin;
+private:
+  mystringrep* rep;
+
+protected:
+  void dupnil();
+  void dup(const char*, size_t);
+  void dup(const char*);
+  void append(const char*);
+  void append(const char*, size_t);
+  void assign(const char*);
+  void assign(const char*, size_t);
+public:
+  static const mystring NUL;
+  
+  mystring() { dupnil(); }
+  mystring(const char* s) { dup(s); }
+  mystring(const mystring& s) { dup(s.rep->buf, s.rep->length); }
+  mystring(const char* str, size_t len) { dup(str, len); }
+  mystring(const mystringjoin&);
+  ~mystring();
+
+  const char* c_str() const { return rep->buf; }
+
+  bool operator!() const { return empty(); }
+  
+  char operator[](size_t i) const { return rep->buf[i]; }
+  
+  size_t length() const { return rep->length; }
+
+  bool empty() const { return rep->length == 0; }
+  
+  int operator!=(const char* in) const;
+  int operator!=(const mystring& in) const;
+  bool operator==(const char* in) const
+    {
+      return !operator!=(in);
+    }
+  bool operator==(const mystring& in) const
+    {
+      return !operator!=(in);
+    }
+
+  void operator=(const char* in) { assign(in); }
+  void operator=(const mystring& in) { assign(in.rep->buf, in.rep->length); }
+  void operator=(const mystringjoin& in);
+
+  mystring subst(char from, char to) const;
+  
+  mystring lower() const;
+  mystring upper() const;
+
+  int find_first(char, size_t = 0) const;
+  int find_first_of(const mystring&, size_t = 0) const;
+  int find_first_of(const char*, size_t = 0) const;
+  int find_first_of(const char*, size_t, size_t) const;
+
+  int find_last(char, size_t = (size_t)-1) const;
+  int find_last_of(const mystring&, size_t = (size_t)-1) const;
+  int find_last_of(const char*, size_t = 0) const;
+  int find_last_of(const char*, size_t, size_t) const;
+
+  mystring left(size_t) const;
+  mystring right(size_t) const;
+  mystring sub(size_t, size_t) const;
+
+  mystring lstrip() const;
+  mystring rstrip() const;
+  mystring strip() const;
+
+  unsigned count(char ch) const;
+  
+  void operator+=(const mystring& str) {append(str.rep->buf, str.rep->length);}
+  void operator+=(const char* str) { append(str); }
+  void operator+=(char ch)
+    {
+      char str[2] = { ch, 0 };
+      append(str, 1);
+    }
+};
+
+#ifndef MYSTRING_TRACE
+inline mystring::~mystring()
+{
+  rep->detach();
+}
+#endif
+
+#include "mystring/iter.h"
+#include "mystring/join.h"
+
+class fdobuf;
+fdobuf& operator<<(fdobuf& out, const mystring& str);
+
+//istream& operator>>(istream& in, mystring& str);
+
+typedef mystring string;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/rep.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,157 @@
+#include "mystring.h"
+#include "trace.h"
+#include <ctype.h>
+#include <string.h>
+
+mystringrep nil = { 0, 1, 1, "" };
+
+static const unsigned replength = sizeof(unsigned)*3;
+
+static const unsigned sizestep = sizeof(unsigned);
+static const unsigned slackdiv = 4;
+static const unsigned slackmax = 16;
+
+#ifdef MYSTRINGREP_STATS
+
+#include "fdbuf.h"
+
+struct _rep_stats
+{
+  unsigned allocs;
+  unsigned alloc_size;
+  unsigned alloc_len;
+  
+  unsigned appends;
+  unsigned appends_dup;
+
+  _rep_stats()
+    : allocs(0)
+    {
+    }
+  
+  void stat(const char* name, unsigned value)
+    {
+      ferr << "mystringrep: " << name << ": " << value << '\n';
+    }
+  void pcnt(const char* name, unsigned denom, unsigned divis)
+    {
+      ferr << "mystringrep: " << name << ": "
+	   << denom << '/' << divis << '=';
+      if(divis) ferr << denom * 100 / divis << '%';
+      else ferr << "N/A";
+      ferr << '\n';
+    }
+  
+  ~_rep_stats()
+    {
+      stat("     size step", sizestep);
+      stat(" slack divisor", slackdiv);
+      stat(" slack maximum", slackmax);
+      stat("        allocs", allocs);
+      stat("  alloc length", alloc_len);
+      stat("    alloc size", alloc_size);
+      pcnt("   alloc slack", alloc_size-alloc_len, alloc_len);
+      stat("alloc overhead", allocs*replength);
+      pcnt("  appends->dup", appends_dup, appends);
+    }
+};
+
+static _rep_stats stats;
+
+#define ACCOUNT(NAME,VALUE) stats. NAME += VALUE
+
+#else // MYSTRINGREP_STATS
+
+#define ACCOUNT(NAME,VALUE)
+
+#endif // MYSTRINGREP_STATS
+
+///////////////////////////////////////////////////////////////////////////////
+// class mystringrep
+///////////////////////////////////////////////////////////////////////////////
+mystringrep* mystringrep::alloc(unsigned length)
+{
+  ACCOUNT(allocs, 1);
+  trace_static("length=" << length);
+  if(length == 0)
+    return &nil;
+
+  ACCOUNT(alloc_len, length);
+  unsigned slack = length / slackdiv;
+  if(slack > slackmax)
+    slack = slackmax;
+  unsigned size = length+1 + sizestep-1 + slack;
+  size = size - size % sizestep;
+  ACCOUNT(alloc_size, size);
+
+  mystringrep* ptr = (mystringrep*)new char[size+replength];
+  ptr->length = length;
+  ptr->references = 0;
+  ptr->size = size;
+  return ptr;
+}
+
+mystringrep* mystringrep::dup(const char* str, unsigned length)
+{
+  trace_static("str=" << (void*)str << " length=" << length);
+  if(length == 0)
+    return &nil;
+  mystringrep* ptr = alloc(length);
+  memcpy(ptr->buf, str, length);
+  ptr->buf[length] = 0;
+  return ptr;
+}
+
+mystringrep* mystringrep::dup(const char* str1, unsigned length1,
+			      const char* str2, unsigned length2)
+{
+  trace_static("");
+  if(length1+length2 == 0)
+    return &nil;
+  mystringrep* ptr = alloc(length1+length2);
+  memcpy(ptr->buf, str1, length1);
+  memcpy(ptr->buf+length1, str2, length2);
+  ptr->buf[length1+length2] = 0;
+  return ptr;
+}
+
+mystringrep* mystringrep::append(const char* str, unsigned len)
+{
+  ACCOUNT(appends, 1);
+  unsigned newlen = length + len;
+  // If there are more than one references, always make a duplicate
+  // Also, if this does not have enough space to add the new string, dup it
+  if(references > 1 || newlen >= size) {
+    ACCOUNT(appends_dup, 1);
+    mystringrep* tmp = dup(buf, length, str, len);
+    tmp->attach();
+    detach();
+    return tmp;
+  }
+  // Otherwise, just add the new string to the end of this
+  else {
+    memcpy(buf+length, str, len);
+    buf[newlen] = 0;
+    length = newlen;
+    return this;
+  }
+}
+
+#ifdef MYSTRING_TRACE    
+void mystringrep::attach()
+{
+  trace("references=" << references);
+  ++references;
+}
+#endif
+
+void mystringrep::detach()
+{
+  trace("references=" << references);
+  
+  --references;
+  if(!references) {
+    trace("deleting this");
+    delete this;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/rep.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,46 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef MYSTRING__REP__H__
+#define MYSTRING__REP__H__
+
+struct mystringrep
+{
+  unsigned length;
+  unsigned references;
+  unsigned size;
+  char buf[1];
+
+  void attach();
+  void detach();
+  mystringrep* append(const char*, unsigned);
+  
+  static mystringrep* alloc(unsigned);
+  static mystringrep* dup(const char*, unsigned);
+  static mystringrep* dup(const char*, unsigned,
+			  const char*, unsigned);
+};
+
+#ifndef MYSTRING_TRACE
+inline void mystringrep::attach()
+{
+  references++;
+}
+#endif
+
+extern mystringrep nil;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/rstrip.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "mystring.h"
+#include <ctype.h>
+
+mystring mystring::rstrip() const
+{
+  const char* ptr = rep->buf + rep->length - 1;
+  while(ptr >= rep->buf && isspace(*ptr))
+    --ptr;
+  return mystring(rep->buf, ptr-rep->buf+1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/strip.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,13 @@
+#include "mystring.h"
+#include <ctype.h>
+
+mystring mystring::strip() const
+{
+  const char* start = rep->buf;
+  while(*start && isspace(*start))
+    ++start;
+  const char* end = rep->buf + rep->length - 1;
+  while(end >= start && isspace(*end))
+    --end;
+  return mystring(start, end-start+1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/sub.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,37 @@
+#include "mystring.h"
+
+// return the sub-string ending at 'offset'
+mystring mystring::left(size_t offset) const
+{
+  if(offset > rep->length)
+    return *this;
+  else
+    return mystring(rep->buf, offset);
+}
+
+// return the sub-string starting at 'offset'
+mystring mystring::right(size_t offset) const
+{
+  if(offset >= rep->length)
+    return mystring();
+  else if(offset == 0)
+    return *this;
+  else
+    return mystring(rep->buf+offset, rep->length-offset);
+}
+
+// return the 'len' characters of the string starting at 'offset'
+mystring mystring::sub(size_t offset, size_t len) const
+{
+  // return right(offset).left(len);
+  if(len == 0)
+    return mystring();
+  else if(offset == 0 && len >= rep->length)
+    return *this;
+  else {
+    if(len+offset >= rep->length)
+      len = rep->length - offset;
+    return mystring(rep->buf+offset, len);
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/subst.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,18 @@
+#include "mystring.h"
+
+mystring mystring::subst(char from, char to) const
+{
+  const unsigned length = rep->length;
+  char buf[length+1];
+  const char* in = rep->buf + length;
+  bool changed = true;
+  for(char* out = buf+length; out >= buf; in--, out--)
+    if(*in == from)
+      *out = to, changed = true;
+    else
+      *out = *in;
+  if(!changed)
+    return *this;
+  else
+    return mystring(buf, length);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/trace.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,10 @@
+#include "mystring.h"
+
+#ifdef MYSTRING_TRACE
+ostream& operator<<(ostream& out, const mystringtmp& s);
+#define trace(X) cerr << (void*)this << "->" << __PRETTY_FUNCTION__ << X << endl
+#define trace_static(X) cerr << __PRETTY_FUNCTION__ << X << endl
+#else
+#define trace(X) do { } while(0)
+#define trace_static(X) do { } while(0)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/mystring/upper.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,21 @@
+#include "mystring.h"
+#include <ctype.h>
+			
+mystring mystring::upper() const
+{
+  const unsigned length = rep->length;
+  char buf[length+1];
+  const char* in = rep->buf + length;
+  bool changed = false;
+  for(char* out = buf+length; out >= buf; in--, out--)
+    if(isupper(*in)) {
+      *out = tolower(*in);
+      changed = true;
+    }
+    else
+      *out = *in;
+  if(!changed)
+    return *this;
+  else
+    return mystring(buf, length);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,12 @@
+noinst_LIBRARIES = libvdomain.a
+INCLUDES = -I..
+EXTRA_DIST = vdomain.h
+
+libvdomain_a_SOURCES = \
+	vdomain.cc \
+	chattr.cc \
+	deluser.cc \
+	lookup.cc \
+	set.cc \
+	userdir.cc \
+	validate.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,317 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libvdomain.a
+INCLUDES = -I..
+EXTRA_DIST = vdomain.h
+
+libvdomain_a_SOURCES =  	vdomain.cc 	chattr.cc 	deluser.cc 	lookup.cc 	set.cc 	userdir.cc 	validate.cc
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libvdomain_a_LIBADD = 
+libvdomain_a_OBJECTS =  vdomain.o chattr.o deluser.o lookup.o set.o \
+userdir.o validate.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libvdomain_a_SOURCES)
+OBJECTS = $(libvdomain_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/vdomain/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libvdomain.a: $(libvdomain_a_OBJECTS) $(libvdomain_a_DEPENDENCIES)
+	-rm -f libvdomain.a
+	$(AR) cru libvdomain.a $(libvdomain_a_OBJECTS) $(libvdomain_a_LIBADD)
+	$(RANLIB) libvdomain.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/vdomain
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+chattr.o: chattr.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h ../misc/pwcrypt.h ../misc/autodelete.h \
+	../misc/strtou.h
+deluser.o: deluser.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h ../misc/autodelete.h ../misc/maildir.h
+lookup.o: lookup.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h ../misc/autodelete.h
+set.o: set.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h ../misc/maildir.h
+userdir.o: userdir.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h ../misc/crc_hash.h ../misc/crc32.h
+validate.o: validate.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h
+vdomain.o: vdomain.cc ../../config.h vdomain.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../config/configrc.h ../misc/strlist.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/chattr.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,100 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include "vdomain.h"
+#include "misc/pwcrypt.h"
+#include "misc/autodelete.h"
+#include "misc/strtou.h"
+
+static const response
+  resp_invalid_number(response::err, "Invalid number"),
+  resp_attribute_changed(response::ok, "Attribute value changed");
+
+response vdomain::chattr(mystring username, unsigned attr, mystring newval)
+{
+  autodelete<vpwentry> vpw = table()->getbyname(username);
+  if(!vpw)
+    RETURN(err, "Invalid or unknown virtual user");
+  return chattr(vpw, attr, newval);
+}
+
+static response chunsigned(unsigned* value, mystring newval)
+{
+  const char* end;
+  *value = strtou(newval.c_str(), &end);
+  if(*end)
+    return resp_invalid_number;
+  else
+    return resp_attribute_changed;
+}
+
+response vdomain::chpass(vpwentry* vpw, mystring pass)
+{
+  vpw->pass = pwcrypt(pass);
+  RETURN(ok, "Password changed");
+}
+
+response vdomain::chdest(vpwentry* vpw, mystring dest)
+{
+  if(!!dest) {
+    for(mystring_iter iter = dest; iter; ++iter) {
+      response r = validate_forward(*iter);
+      if(!r)
+	return r;
+    }
+  }
+  vpw->forwards = dest;
+  RETURN(ok, "Forwarding address(es) changed");
+}
+
+static response chbool(bool* value, mystring newval)
+{
+  const char* end;
+  unsigned i = strtou(newval.c_str(), &end);
+  if(*end)
+    return resp_invalid_number;
+  *value = !!i;
+  return resp_attribute_changed;
+}
+  
+#define CHATTR(V,X) do{ response tmp=ch##X(&(V),newval); if(!tmp) return tmp; okmsg=tmp.msg; }while(0)
+
+response vdomain::chattr(const vpwentry* vpw, unsigned attr, mystring newval)
+{
+  vpwentry newpw(*vpw);
+  mystring okmsg;
+  switch(attr) {
+  case ATTR_PASS:              CHATTR(newpw,pass); break;
+  case ATTR_DEST:              CHATTR(newpw,dest); break;
+  case ATTR_HARDQUOTA:         CHATTR(newpw.hardquota,unsigned); break;
+  case ATTR_SOFTQUOTA:         CHATTR(newpw.softquota,unsigned); break;
+  case ATTR_MSGSIZE:           CHATTR(newpw.msgsize,unsigned); break;
+  case ATTR_MSGCOUNT:          CHATTR(newpw.msgcount,unsigned); break;
+  case ATTR_EXPIRY:            CHATTR(newpw.expiry,unsigned); break;
+  case ATTR_MAILBOX_ENABLED:   CHATTR(newpw.is_mailbox_enabled,bool); break;
+  case ATTR_PERSONAL:
+    newpw.personal = newval;
+    okmsg = "Personal information changed.";
+    break;
+  default:
+    RETURN(bad, "Invalid attribute type");
+  }
+  if(!table()->set(&newpw))
+    RETURN(err, "Error changing the password table");
+  RETURN(ok, okmsg);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/deluser.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,35 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vdomain.h"
+#include "misc/autodelete.h"
+#include "misc/maildir.h"
+
+response vdomain::deluser(mystring user, bool del_mailbox)
+{
+  user = user.lower();
+  autodelete<vpwentry> vpw = table()->getbyname(user);
+  if(!vpw)
+    RETURN(err, "User does not exist");
+  if(!del_mailbox && !!vpw->mailbox)
+    RETURN(err, "User has a mailbox");
+  if(!table()->del(vpw->name))
+    RETURN(err, "Couldn't delete user from the password file");
+  if(!!vpw->mailbox && !delete_directory(vpw->mailbox))
+    RETURN(err, "Couldn't delete user's mail directory");
+  RETURN(ok, "Deleted user.");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/lookup.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,51 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vdomain.h"
+#include "misc/autodelete.h"
+
+#if 0
+response vdomain::lookup(mystring username)
+{
+  autodelete<vpwentry> vpw = table()->getbyname(username);
+  if(!vpw)
+    RETURN(err, "Invalid or unknown virtual user");
+  const mystring dest = vpw->dest;
+  if(dest.empty())
+    RETURN(err, "Invalid virtual password entry");
+  else
+    RETURN(ok, dest);
+}
+#endif
+
+bool vdomain::exists(mystring name)
+{
+  return table()->exists(name);
+}
+
+vpwentry* vdomain::lookup(mystring name, bool nodefault)
+{
+  vpwentry* vpw;
+  if(!name)
+    vpw = 0;
+  else {
+    vpw = table()->getbyname(name);
+    if(!vpw && !nodefault)
+      vpw = table()->getbyname(config.default_username());
+  }
+  return vpw;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/set.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,40 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vdomain.h"
+#include "misc/maildir.h"
+
+response vdomain::set(const vpwentry* vpw, bool onlyadd,
+		      mystring maildir)
+{
+  if(!vpw)
+    RETURN(err, "Internal error: no vpwentry");
+  if(!validate_username(vpw->name))
+    RETURN(bad, "Virtual user or alias name contains invalid characters");
+  if(!validate_password(vpw->pass))
+    RETURN(bad, "Password field contains invalid characters");
+  if(!!maildir && !make_maildir(maildir.c_str()))
+    RETURN(err, "Can't create the mail directory '" + maildir + "'");
+  if(!table()->put(vpw, onlyadd)) {
+    if(!!maildir)
+      delete_directory(maildir.c_str());
+    RETURN(err, "Can't add the user to the password file");
+  }
+  RETURN(ok, !maildir
+	 ? "Alias added successfully"
+	 : "User added successfully");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/userdir.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,44 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vdomain.h"
+#include "misc/crc_hash.h"
+
+mystring vdomain::userdir(mystring username) const
+{
+  unsigned slices = config.user_dir_slices();
+  unsigned bits = config.user_dir_bits();
+  static crc_hash hasher;
+  static const char bin2hex[16+1] = "0123456789abcdef";
+  unsigned hash = hasher(username);
+  mystring dir = config.user_dir();
+  const unsigned hexdigits = (bits+3)/4;
+  const unsigned bitmask = ~(~0U << bits);
+  char hexbuf[hexdigits+1];
+  hexbuf[hexdigits] = 0;
+  for(; slices > 0; --slices, hash >>= bits) {
+    unsigned slice = hash & bitmask;
+    for(unsigned i = hexdigits; i > 0; --i, slice >>= 4)
+      hexbuf[i-1] = bin2hex[slice & 0xf];
+    dir += hexbuf;
+    dir += "/";
+  }
+  dir += username.subst('.', ':');
+  if(!!subdir)
+    dir = subdir + "/" + dir;
+  return dir;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/validate.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,50 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vdomain.h"
+
+static bool validate_field(mystring str, const char* bad_chars)
+{
+  if(!str)
+    return false;
+  if(str.find_first_of(bad_chars) >= 0)
+    return false;
+  return true;
+}
+
+bool vdomain::validate_username(mystring user) const
+{
+  return validate_field(user, "/:\n\r\t ");
+}
+
+bool vdomain::validate_password(mystring pass) const
+{
+  return validate_field(pass, ":\n\r\t ");
+}
+
+response vdomain::validate_forward(mystring forward)
+{
+  int atchar = forward.find_first('@');
+  if(atchar < 0) {
+    if(!exists(forward))
+      RETURN(err, "User '" + forward + "' does not exist");
+  }
+  else if(forward.find_first('@', atchar+1) >= 0)
+    RETURN(err, "Address '" + forward + "' is invalid: "
+	   "  Address contains more than one at (@) symbol");
+  RETURN(ok, "");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/vdomain.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,50 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vdomain.h"
+
+// The default constructor creates a virtual domain profile for the
+// situation where the user owns a single domain
+vdomain::vdomain(const pwentry& user)
+  : subdir(), prefix(),
+    config(&user.config, user.home + "/" LOCAL_CONFIG_DIR),
+    ptable(0)
+{
+}
+
+#if 0
+// This constructor creates a profile for the situation where the user
+// owns multiple domains (NOT FULLY IMPLEMENTED YET)
+vdomain::vdomain(const pwentry& user,
+		 mystring sd, mystring pf)
+  : subdir(sd), prefix(pf),
+    config(&user.config, user.home + "/" + sd + "/" LOCAL_CONFIG_DIR),
+    ptable(0)
+{
+}
+#endif
+
+vdomain::~vdomain()
+{
+}
+
+vpwtable* vdomain::table()
+{
+  if(!ptable)
+    ptable = new vpwtable(this);
+  return ptable;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vdomain/vdomain.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,56 @@
+#ifndef VMAILMGR__VDOMAIN__H__
+#define VMAILMGR__VDOMAIN__H__
+
+#include "mystring/mystring.h"
+#include "config/configrc.h"
+#include "misc/pwentry.h"
+#include "vpwtable/vpwtable.h"
+#include "misc/response.h"
+
+class vdomain
+{
+public:
+  const mystring subdir;
+  const mystring prefix;
+  const configuration config;
+private:
+  vpwtable* ptable;
+
+  // Helper functions for chattr
+  response chpass(vpwentry*, mystring);
+  response chdest(vpwentry*, mystring);
+public:
+  vdomain(const pwentry&);
+  vdomain(const pwentry&, mystring, mystring, const configuration&);
+  ~vdomain();
+
+  vpwtable* table();
+  
+  mystring userdir(mystring username) const;
+
+  // Virtual user manipulation functions
+  vpwentry* lookup(mystring name, bool nodefault);
+  bool exists(mystring name);
+  
+  response set(const vpwentry*, bool onlyadd, mystring maildir = "");
+  response chattr(mystring user, unsigned attr, mystring newval);
+  response chattr(const vpwentry*, unsigned attr, mystring newval);
+  response deluser(mystring name, bool del_mailbox);
+
+  // Virtual user validation functions
+  response validate_forward(mystring);
+  bool validate_username(mystring) const;
+  bool validate_password(mystring) const;
+
+  static const unsigned ATTR_PASS = 1;
+  static const unsigned ATTR_DEST = 2;
+  static const unsigned ATTR_HARDQUOTA = 3;
+  static const unsigned ATTR_SOFTQUOTA = 4;
+  static const unsigned ATTR_MSGSIZE = 5;
+  static const unsigned ATTR_MSGCOUNT = 6;
+  static const unsigned ATTR_EXPIRY = 7;
+  static const unsigned ATTR_MAILBOX_ENABLED = 8;
+  static const unsigned ATTR_PERSONAL = 9;
+};
+
+#endif // VMAILMGR__VDOMAIN__H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,15 @@
+noinst_LIBRARIES = libvpwentry.a
+INCLUDES = -I..
+EXTRA_DIST = vpwentry.h
+
+libvpwentry_a_SOURCES = \
+	auth.cc \
+	decode.cc \
+	defaults.cc \
+	export_env.cc \
+	from.cc \
+	from_old.cc \
+	from_ver1.cc \
+	from_ver2.cc \
+	to.cc \
+	vpwentry.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,323 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libvpwentry.a
+INCLUDES = -I..
+EXTRA_DIST = vpwentry.h
+
+libvpwentry_a_SOURCES =  	auth.cc 	decode.cc 	defaults.cc 	export_env.cc 	from.cc 	from_old.cc 	from_ver1.cc 	from_ver2.cc 	to.cc 	vpwentry.cc
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libvpwentry_a_LIBADD = 
+libvpwentry_a_OBJECTS =  auth.o decode.o defaults.o export_env.o from.o \
+from_old.o from_ver1.o from_ver2.o to.o vpwentry.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libvpwentry_a_SOURCES)
+OBJECTS = $(libvpwentry_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/vpwentry/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libvpwentry.a: $(libvpwentry_a_OBJECTS) $(libvpwentry_a_DEPENDENCIES)
+	-rm -f libvpwentry.a
+	$(AR) cru libvpwentry.a $(libvpwentry_a_OBJECTS) $(libvpwentry_a_LIBADD)
+	$(RANLIB) libvpwentry.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/vpwentry
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+auth.o: auth.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../misc/pwcrypt.h
+decode.o: decode.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vdomain/vdomain.h ../config/configrc.h \
+	../misc/pwentry.h ../vpwtable/vpwtable.h ../vpwentry/vpwentry.h \
+	../misc/response.h ../misc/strtou.h
+defaults.o: defaults.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../config/configrc.h
+disable.o: disable.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../misc/stat_fns.h
+export_env.o: export_env.cc ../../config.h vpwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../misc/exec.h \
+	../vpwentry/vpwentry.h ../misc/utoa.h
+from.o: from.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h
+from_old.o: from_old.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h
+from_uint.o: from_uint.cc ../../config.h ../misc/strtou.h
+from_ver1.o: from_ver1.cc ../../config.h vpwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h
+from_ver2.o: from_ver2.cc ../../config.h vpwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h
+is_enabled.o: is_enabled.cc ../../config.h vpwentry.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../misc/stat_fns.h
+to.o: to.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../misc/utoa.h ../vdomain/vdomain.h \
+	../config/configrc.h ../misc/pwentry.h ../vpwtable/vpwtable.h \
+	../vpwentry/vpwentry.h ../misc/response.h
+vpwentry.o: vpwentry.cc ../../config.h vpwentry.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/auth.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,24 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwentry.h"
+#include "misc/pwcrypt.h"
+
+bool vpwentry::authenticate(const mystring& phrase) const
+{
+  return crypt_cmp(phrase, pass);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/decode.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,86 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <string.h>
+#include "vpwentry.h"
+#include "vdomain/vdomain.h"
+#include "misc/strtou.h"
+
+static const char* from_uint(const char* ptr, unsigned& uint)
+{
+  const char* tmp;
+  uint = strtou(ptr, &tmp);
+  return (*tmp == 0) ? ++tmp : 0;
+}
+
+const char* vpwentry::decode_flags(const char* ptr, const char* end)
+{
+  while(ptr < end) {
+    unsigned flag = *(unsigned char*)ptr++;
+    if(!flag)
+      return ptr;
+    if(ptr >= end)
+      return 0;
+    bool value = *(unsigned char*)ptr++;
+    switch(flag) {
+    case vdomain::ATTR_MAILBOX_ENABLED:
+      is_mailbox_enabled = value;
+      break;
+    default:
+      return 0;
+    }
+  }
+  return 0;
+}
+
+const char* vpwentry::decode_base(const char* ptr, const char* end)
+{
+  pass = ptr;
+  ptr += pass.length() + 1;
+  if(ptr >= end) return 0;
+  
+  mailbox = ptr;
+  ptr += mailbox.length() + 1;
+  if(ptr >= end) return 0;
+  
+  const char* start = ptr;
+  while(ptr < end && *ptr != 0)
+    ptr += strlen(ptr) + 1;
+  if(ptr == start)
+    forwards = "";
+  else
+    forwards = mystring(start, ptr-start-1);
+  if(ptr++ >= end) return 0;
+  
+  personal = ptr;
+  ptr += personal.length() + 1;
+  if(ptr >= end) return 0;
+  
+  return ptr;
+}
+
+const char* vpwentry::decode_values(const char* ptr, const char* end)
+{
+  if((ptr = from_uint(ptr, hardquota)) == 0 || ptr >= end) return 0;
+  if((ptr = from_uint(ptr, softquota)) == 0 || ptr >= end) return 0;
+  if((ptr = from_uint(ptr, msgsize)) == 0 || ptr >= end) return 0;
+  if((ptr = from_uint(ptr, msgcount)) == 0 || ptr >= end) return 0;
+  if((ptr = from_uint(ptr, ctime)) == 0 || ptr >= end) return 0;
+  if((ptr = from_uint(ptr, expiry)) == 0 || ptr > end) return 0;
+  return ptr;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/defaults.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,45 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <time.h>
+#include <limits.h>
+#include "vpwentry.h"
+#include "config/configrc.h"
+
+void vpwentry::set_defaults(bool ctime_now, bool set_flags)
+{
+  softquota = config->default_softquota();
+  hardquota = config->default_hardquota();
+  msgsize = config->default_msgsize();
+  msgcount = config->default_msgcount();
+  unsigned now = time(0);
+  if(ctime_now)
+    ctime = now;
+  else
+    ctime = 0;
+  unsigned de = config->default_expiry();
+  if(de == UINT_MAX)
+    expiry = de;
+  else {
+    expiry = now + de;
+    if(expiry < now)
+      expiry = UINT_MAX;
+  }
+  if(set_flags) {
+    is_mailbox_enabled = true;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/export_env.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,41 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwentry.h"
+#include "misc/exec.h"
+#include "misc/utoa.h"
+
+static int presetenv(const char* prefix, unsigned value)
+{
+  return presetenv(prefix, utoa(value));
+}
+
+bool vpwentry::export_env() const
+{
+  return presetenv("VUSER=", name) == 0 &&
+    presetenv("MAILDIR=", mailbox) == 0 &&
+    presetenv("VUSER_CTIME=", ctime) == 0 &&
+    presetenv("VUSER_EXPIRY=", expiry) == 0 &&
+    presetenv("VUSER_MSGCOUNT=", msgcount) == 0 &&
+    presetenv("VUSER_MSGSIZE=", msgsize) == 0 &&
+    presetenv("VUSER_PERSONAL=", personal) == 0 &&
+    presetenv("VUSER_HARDQUOTA=", hardquota) == 0 &&
+    presetenv("VUSER_SOFTQUOTA=", softquota) == 0 &&
+    presetenv("VUSER_MAILBOX_ENABLED=", is_mailbox_enabled) == 0;
+  //for(mystring_iter iter(data.str(), '\0'); iter; ++iter)
+  //  presetenv("VUSER_"+...+"=", *iter);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/from.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,33 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwentry.h"
+
+bool vpwentry::from_record(const mystring& vname, const mystring& text)
+{
+  name = vname;
+  switch(text[0]) {
+  case 2:
+    return from_ver2_record(text);
+  case 1:
+    return from_ver1_record(text);
+  case ':':
+    return from_old_record(text);
+  default:
+    return false;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/from_old.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,43 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <string.h>
+#include "vpwentry.h"
+
+bool vpwentry::from_old_record(const mystring& text)
+{
+  const char* passptr = text.c_str()+1;
+  const char* end = strchr(passptr, ':');
+  if(!end) return false;
+
+  pass = text.sub(1, end-passptr);
+  ++end;
+  if(*end == '.' || *end == '/') {
+    mailbox = end;
+    forwards = 0;
+  }
+  else {
+    if(*end == '&')
+      ++end;
+    mailbox = 0;
+    forwards = end;
+    forwards = forwards.subst(',', '\0');
+  }
+  set_defaults(false, true);
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/from_ver1.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,39 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <string.h>
+#include "vpwentry.h"
+
+bool vpwentry::from_ver1_record(const mystring& text)
+{
+  // Sanity check to ensure that text conversions can't
+  // fall off the end of the string.
+  if(text[text.length()-1] != 0)
+    return false;
+
+  const char* ptr = text.c_str();
+  const char* const end = ptr++ + text.length();
+
+  if((ptr = decode_base(ptr, end)) == 0) return false;
+  if((ptr = decode_values(ptr, end)) == 0) return false;
+  
+  // Set defaults
+  is_mailbox_enabled = true;
+  
+  return ptr == end;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/from_ver2.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,39 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <ctype.h>
+#include <string.h>
+#include "vpwentry.h"
+
+bool vpwentry::from_ver2_record(const mystring& text)
+{
+  // Sanity check to ensure that text conversions can't
+  // fall off the end of the string.
+  if(text[text.length()-1] != 0)
+    return false;
+
+  const char* ptr = text.c_str();
+  const char* const end = ptr++ + text.length();
+
+  if((ptr = decode_flags(ptr, end)) == 0) return false;
+  if((ptr = decode_base(ptr, end)) == 0) return false;
+  if((ptr = decode_values(ptr, end)) == 0) return false;
+  
+  //data = ptr;
+  
+  return ptr == end;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/to.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,45 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwentry.h"
+#include "misc/utoa.h"
+#include "vdomain/vdomain.h"
+
+mystring vpwentry::to_record() const
+{
+  static const mystring prefix = "\02";
+  
+  mystring f;
+  if(!!forwards)
+    f = forwards + mystring::NUL;
+  char flagstmp[] = {
+    vdomain::ATTR_MAILBOX_ENABLED,
+    is_mailbox_enabled,
+    0
+  };
+  mystring flags(flagstmp, 3);
+  return prefix + flags + pass + mystring::NUL +
+    mailbox + mystring::NUL +
+    f + mystring::NUL +
+    personal + mystring::NUL +
+    utoa(hardquota) + mystring::NUL +
+    utoa(softquota) + mystring::NUL +
+    utoa(msgsize) + mystring::NUL +
+    utoa(msgcount) + mystring::NUL +
+    utoa(ctime) + mystring::NUL +
+    utoa(expiry) + mystring::NUL /* + data.str() + mystring::NUL */ ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/vpwentry.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,34 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwentry.h"
+
+vpwentry::vpwentry()
+  : is_mailbox_enabled(true)
+{
+}
+
+vpwentry::vpwentry(const mystring& n, const mystring& p,
+		   const mystring& m, const mystring& f)
+  : name(n), pass(p), mailbox(m), forwards(f),
+    is_mailbox_enabled(true)
+{
+}
+
+vpwentry::~vpwentry()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwentry/vpwentry.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,53 @@
+#ifndef VMAILMGR__VPWENTRY__H__
+#define VMAILMGR__VPWENTRY__H__
+
+#include "mystring/mystring.h"
+#include "misc/strlist.h"
+
+struct vpwentry 
+{
+protected:
+  const char* decode_flags(const char*, const char*);
+  const char* decode_base(const char*, const char*);
+  const char* decode_values(const char*, const char*);
+
+  bool from_ver1_record(const mystring& text);
+  bool from_ver2_record(const mystring& text);
+  bool from_old_record(const mystring& text);
+  
+public:
+  mystring name;
+  mystring pass;
+  mystring mailbox;
+  mystring forwards;
+  mystring personal;
+  unsigned hardquota;
+  unsigned softquota;
+  unsigned msgsize;
+  unsigned msgcount;
+  unsigned ctime;
+  unsigned expiry;
+  bool is_mailbox_enabled;
+  // keystrlist data;
+  
+  vpwentry();
+  vpwentry(const mystring&, const mystring&, const mystring&, const mystring&);
+  ~vpwentry();
+
+  //mystring get(const mystring& var) const { return data.get(var); }
+  //void set(const mystring& var, const mystring& val)
+  //  {
+  //    return data.set(var, val);
+  //  }
+
+  void set_defaults(bool ctime_now, bool set_flags);
+
+  bool authenticate(const mystring& phrase) const;
+  
+  bool from_record(const mystring& name, const mystring& text);
+  mystring to_record() const;
+
+  bool export_env() const;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,42 @@
+noinst_LIBRARIES = libvpwtable.a
+INCLUDES = -I..
+EXTRA_DIST = vpwtable.h \
+	cdb_vpwtable.cc \
+	cdb_del.cc \
+	cdb_exists.cc \
+	cdb_getbyname.cc \
+	cdb_put.cc \
+	cdb_read.cc \
+	gdbm_vpwtable.cc \
+	gdbm_del.cc \
+	gdbm_exists.cc \
+	gdbm_getbyname.cc \
+	gdbm_put.cc \
+	gdbm_read.cc
+
+if VPWTABLE_CDB
+CDBSOURCES = \
+	cdb_vpwtable.cc \
+	cdb_del.cc \
+	cdb_exists.cc \
+	cdb_getbyname.cc \
+	cdb_put.cc \
+	cdb_read.cc
+else
+CDBSOURCES =
+endif
+
+if VPWTABLE_GDBM
+GDBMSOURCES = \
+	gdbm_vpwtable.cc \
+	gdbm_del.cc \
+	gdbm_exists.cc \
+	gdbm_getbyname.cc \
+	gdbm_put.cc \
+	gdbm_read.cc
+else
+GDBMSOURCES =
+endif
+
+libvpwtable_a_SOURCES = $(CDBSOURCES) $(GDBMSOURCES) \
+	reader.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,392 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+noinst_LIBRARIES = libvpwtable.a
+INCLUDES = -I..
+EXTRA_DIST = vpwtable.h 	cdb_vpwtable.cc 	cdb_del.cc 	cdb_exists.cc 	cdb_getbyname.cc 	cdb_put.cc 	cdb_read.cc 	gdbm_vpwtable.cc 	gdbm_del.cc 	gdbm_exists.cc 	gdbm_getbyname.cc 	gdbm_put.cc 	gdbm_read.cc
+
+@VPWTABLE_CDB_TRUE@CDBSOURCES = 	cdb_vpwtable.cc 	cdb_del.cc 	cdb_exists.cc 	cdb_getbyname.cc 	cdb_put.cc 	cdb_read.cc
+@VPWTABLE_CDB_FALSE@CDBSOURCES = 
+@VPWTABLE_GDBM_TRUE@GDBMSOURCES = 	gdbm_vpwtable.cc 	gdbm_del.cc 	gdbm_exists.cc 	gdbm_getbyname.cc 	gdbm_put.cc 	gdbm_read.cc
+@VPWTABLE_GDBM_FALSE@GDBMSOURCES = 
+
+libvpwtable_a_SOURCES = $(CDBSOURCES) $(GDBMSOURCES) 	reader.cc
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libvpwtable_a_LIBADD = 
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_TRUE@libvpwtable_a_OBJECTS =  \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_TRUE@cdb_vpwtable.o cdb_del.o \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_TRUE@cdb_exists.o cdb_getbyname.o \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_TRUE@cdb_put.o cdb_read.o \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_TRUE@gdbm_vpwtable.o gdbm_del.o \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_TRUE@gdbm_exists.o gdbm_getbyname.o \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_TRUE@gdbm_put.o gdbm_read.o reader.o
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_FALSE@libvpwtable_a_OBJECTS =  \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_FALSE@cdb_vpwtable.o cdb_del.o \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_FALSE@cdb_exists.o cdb_getbyname.o \
+@VPWTABLE_CDB_TRUE@@VPWTABLE_GDBM_FALSE@cdb_put.o cdb_read.o reader.o
+@VPWTABLE_CDB_FALSE@@VPWTABLE_GDBM_TRUE@libvpwtable_a_OBJECTS =  \
+@VPWTABLE_CDB_FALSE@@VPWTABLE_GDBM_TRUE@gdbm_vpwtable.o gdbm_del.o \
+@VPWTABLE_CDB_FALSE@@VPWTABLE_GDBM_TRUE@gdbm_exists.o gdbm_getbyname.o \
+@VPWTABLE_CDB_FALSE@@VPWTABLE_GDBM_TRUE@gdbm_put.o gdbm_read.o reader.o
+@VPWTABLE_CDB_FALSE@@VPWTABLE_GDBM_FALSE@libvpwtable_a_OBJECTS =  \
+@VPWTABLE_CDB_FALSE@@VPWTABLE_GDBM_FALSE@reader.o
+AR = ar
+CXXFLAGS = @CXXFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libvpwtable_a_SOURCES)
+OBJECTS = $(libvpwtable_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .o .s @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/vpwtable/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+	$(COMPILE) -c $<
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libvpwtable.a: $(libvpwtable_a_OBJECTS) $(libvpwtable_a_DEPENDENCIES)
+	-rm -f libvpwtable.a
+	$(AR) cru libvpwtable.a $(libvpwtable_a_OBJECTS) $(libvpwtable_a_LIBADD)
+	$(RANLIB) libvpwtable.a
+.cc.o:
+	$(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  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)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/vpwtable
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+cdb_del.o: cdb_del.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h ../cdb++/cdb++.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+cdb_exists.o: cdb_exists.cc ../../config.h vpwtable.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../vpwentry/vpwentry.h \
+	../cdb++/cdb++.h ../cdb++/datum.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+cdb_get.o: cdb_get.cc ../../config.h ../misc/autodelete.h \
+	../cdb++/cdb++.h ../mystring/mystring.h ../mystring/rep.h \
+	../mystring/iter.h ../mystring/join.h ../cdb++/datum.h \
+	../fdbuf/fdbuf.h ../fdbuf/fdibuf.h ../fdbuf/fdobuf.h vpwtable.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h
+cdb_getbyname.o: cdb_getbyname.cc ../../config.h vpwtable.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../vpwentry/vpwentry.h \
+	../cdb++/cdb++.h ../cdb++/datum.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+cdb_put.o: cdb_put.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h ../cdb++/cdb++.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+cdb_read.o: cdb_read.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h ../misc/autodelete.h \
+	../cdb++/cdb++.h ../cdb++/datum.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h
+cdb_vpwtable.o: cdb_vpwtable.cc ../../config.h vpwtable.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../vpwentry/vpwentry.h \
+	../vdomain/vdomain.h ../config/configrc.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../misc/response.h
+del.o: del.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h ../cdb++/cdb++.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+exists.o: exists.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h ../cdb++/cdb++.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+gdbm_del.o: gdbm_del.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h
+gdbm_exists.o: gdbm_exists.cc ../../config.h vpwtable.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../vpwentry/vpwentry.h
+gdbm_get.o: gdbm_get.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h
+gdbm_getbyname.o: gdbm_getbyname.cc ../../config.h vpwtable.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../vpwentry/vpwentry.h
+gdbm_put.o: gdbm_put.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h
+gdbm_read.o: gdbm_read.cc ../../config.h vpwtable.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../vpwentry/vpwentry.h
+gdbm_vpwtable.o: gdbm_vpwtable.cc ../../config.h vpwtable.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../misc/strlist.h ../vpwentry/vpwentry.h \
+	../vdomain/vdomain.h ../config/configrc.h ../misc/pwentry.h \
+	../vpwtable/vpwtable.h ../misc/response.h
+get.o: get.cc ../../config.h ../misc/autodelete.h ../cdb++/cdb++.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../cdb++/datum.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h vpwtable.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h
+getbyname.o: getbyname.cc ../../config.h ../cdb++/cdb++.h \
+	../mystring/mystring.h ../mystring/rep.h ../mystring/iter.h \
+	../mystring/join.h ../cdb++/datum.h ../fdbuf/fdbuf.h \
+	../fdbuf/fdibuf.h ../fdbuf/fdobuf.h vpwtable.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h
+put.o: put.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h ../cdb++/cdb++.h \
+	../cdb++/datum.h ../fdbuf/fdbuf.h ../fdbuf/fdibuf.h \
+	../fdbuf/fdobuf.h
+reader.o: reader.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h
+vpwtable.o: vpwtable.cc ../../config.h vpwtable.h ../mystring/mystring.h \
+	../mystring/rep.h ../mystring/iter.h ../mystring/join.h \
+	../misc/strlist.h ../vpwentry/vpwentry.h ../vdomain/vdomain.h \
+	../config/configrc.h ../misc/pwentry.h ../vpwtable/vpwtable.h \
+	../misc/response.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+		mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+		mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+		distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+		maintainer-clean-compile maintainer-clean-tags \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/cdb_del.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,42 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include "cdb++/cdb++.h"
+
+bool vpwtable::del(const mystring& name) const
+{
+  mystring cdbtmpname = filename + ".tmp";
+  cdb_reader in(filename);
+  if(!in) return false; 
+  cdb_writer out(cdbtmpname, 0600);
+  if(!out) return false;
+  
+  bool failed = false;
+  datum* d;
+  mystring lname = name.lower();
+  while(!failed && (d = in.nextrec()) != 0) {
+    if(d->key != name)
+      failed = !out.put(d->key, d->data);
+    delete d;
+  }
+  if(failed)
+    return true;
+  if(!out.end(filename))
+    return false;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/cdb_exists.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,28 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include "cdb++/cdb++.h"
+
+bool vpwtable::exists(const mystring& name) const
+{
+  datum* d = cdb_getrec(filename, name.lower());
+  if(!d)
+    return false;
+  delete d;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/cdb_getbyname.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,33 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include "cdb++/cdb++.h"
+
+vpwentry* vpwtable::getbyname(const mystring& name) const
+{
+  datum* d = cdb_getrec(filename, name.lower());
+  if(!d)
+    return 0;
+  vpwentry v;
+  if(!v.from_record(name, d->data)) {
+    delete d;
+    return 0;
+  }
+  delete d;
+  return new vpwentry(v);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/cdb_put.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,63 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include "vpwtable.h"
+#include "cdb++/cdb++.h"
+
+bool vpwtable::put(const vpwentry* vpw, bool onlyadd) const
+{
+  cdb_reader in(filename);
+  if(!in && errno != ENOENT)
+    return false;
+ 
+  mystring cdbtmpname = filename + ".tmp";
+  cdb_writer out(cdbtmpname, 0600);
+  if(!out)
+    return false;
+
+  mystring lname = vpw->name.lower();
+  if(in) {
+    bool failed = false;
+    datum* d;
+    while(!failed && (d = in.nextrec()) != 0) {
+      if(vpw && d->key == lname) {
+	if(onlyadd)
+	  // names compared equal, but we only wanted to add
+	  failed = true;
+	else if(!out.put(lname, vpw->to_record()))
+	  failed = true;
+	else
+	  vpw = 0;
+      }
+      else
+	failed = !out.put(d->key, d->data);
+      delete d;
+    }
+    if(failed)
+      return false;
+  }
+  if(vpw) {
+    if(!onlyadd)
+      return false;
+    if(!out.put(lname, vpw->to_record()))
+      return false;
+  }
+  if(!out.end(filename))
+    return false;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/cdb_read.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,74 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include <stdlib.h>
+#include "misc/autodelete.h"
+#include "cdb++/cdb++.h"
+
+class cdb_vpwtable_reader : public vpwtable_reader
+{
+private:
+  cdb_reader cdb;
+public:
+  cdb_vpwtable_reader(const mystring& filename);
+  ~cdb_vpwtable_reader();
+  bool operator!() const;
+  bool get(vpwentry& out);
+  bool rewind();
+  bool end();
+};
+
+vpwtable_reader* vpwtable::start_read() const
+{
+  return new cdb_vpwtable_reader(filename);
+}
+
+cdb_vpwtable_reader::cdb_vpwtable_reader(const mystring& filename)
+  : cdb(filename)
+{
+}
+
+cdb_vpwtable_reader::~cdb_vpwtable_reader()
+{
+  end();
+}
+
+bool cdb_vpwtable_reader::operator !() const
+{
+  return !cdb;
+}
+
+bool cdb_vpwtable_reader::end() 
+{
+  return true;
+}
+
+bool cdb_vpwtable_reader::rewind()
+{
+  return !!cdb && cdb.firstrec();
+}
+
+bool cdb_vpwtable_reader::get(vpwentry& out)
+{
+  autodelete<datum> rec = cdb.nextrec();
+  if(!rec)
+    return false;
+  if(!out.from_record(rec->key, rec->data))
+    return false;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/cdb_vpwtable.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,35 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include "vdomain/vdomain.h"
+
+const mystring cdb_extension = ".cdb";
+
+vpwtable::vpwtable(const vdomain* d)
+  : filename(d->config.password_file() + cdb_extension)
+{
+}
+
+vpwtable::vpwtable(const vpwtable& t)
+  : filename(t.filename)
+{
+}
+
+vpwtable::~vpwtable()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/gdbm_del.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,30 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include <gdbm.h>
+
+bool vpwtable::del(const mystring& name) const
+{
+  GDBM_FILE db = gdbm_open((char*)filename.c_str(), 0, GDBM_WRITER, 0, 0);
+  if(!db)
+    return false;
+  datum key = { (char*)name.c_str(), name.length() };
+  bool result = gdbm_delete(db, key) == 0;
+  gdbm_close(db);
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/gdbm_exists.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,30 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include <gdbm.h>
+
+bool vpwtable::exists(const mystring& name) const
+{
+  GDBM_FILE db = gdbm_open((char*)filename.c_str(), 0, GDBM_READER, 0, 0);
+  if(!db)
+    return false;
+  datum key = { (char*)name.c_str(), name.length() };
+  bool result = gdbm_exists(db, key);
+  gdbm_close(db);
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/gdbm_getbyname.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,34 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include <gdbm.h>
+
+vpwentry* vpwtable::getbyname(const mystring& name) const
+{
+  GDBM_FILE db = gdbm_open((char*)filename.c_str(), 0, GDBM_READER, 0, 0);
+  if(!db)
+    return 0;
+  mystring lower = name.lower();
+  datum key = { (char*)lower.c_str(), lower.length() };
+  datum result = gdbm_fetch(db, key);
+  gdbm_close(db);
+  vpwentry v;
+  if(!v.from_record(name, mystring(result.dptr, result.dsize)))
+    return 0;
+  return new vpwentry(v);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/gdbm_put.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,35 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include "vpwtable.h"
+#include <gdbm.h>
+
+bool vpwtable::put(const vpwentry* vpw, bool onlyadd) const
+{
+  GDBM_FILE db = gdbm_open((char*)filename.c_str(), 0, GDBM_WRCREAT, 0600, 0);
+  if(!db)
+    return false;
+  mystring name = vpw->name.lower();
+  datum key = { (char*)name.c_str(), name.length() };
+  mystring binary = vpw->to_record();
+  datum data = { (char*)binary.c_str(), binary.length() };
+  bool result = gdbm_store(db, key, data,
+			   onlyadd ? GDBM_INSERT : GDBM_REPLACE) == 0;
+  gdbm_close(db);
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/gdbm_read.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,93 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include <stdlib.h>
+#include <gdbm.h>
+
+class gdbm_vpwtable_reader : public vpwtable_reader
+{
+private:
+  GDBM_FILE dbf;
+  datum key;
+public:
+  gdbm_vpwtable_reader(const mystring& filename);
+  ~gdbm_vpwtable_reader();
+  bool operator!() const;
+  bool get(vpwentry& out);
+  bool rewind();
+  bool end();
+};
+
+vpwtable_reader* vpwtable::start_read() const
+{
+  return new gdbm_vpwtable_reader(filename);
+}
+
+gdbm_vpwtable_reader::gdbm_vpwtable_reader(const mystring& filename)
+  : dbf(gdbm_open((char*)filename.c_str(), 0, GDBM_READER, 0, 0))
+{
+  if(dbf)
+    key = gdbm_firstkey(dbf);
+  else
+    key.dptr = 0;
+}
+
+gdbm_vpwtable_reader::~gdbm_vpwtable_reader()
+{
+  end();
+}
+
+bool gdbm_vpwtable_reader::operator!() const
+{
+  return !dbf;
+}
+
+bool gdbm_vpwtable_reader::end() 
+{
+  if(dbf)
+    gdbm_close(dbf);
+  if(key.dptr)
+    free(key.dptr);
+  dbf = 0;
+  key.dptr = 0;
+  return true;
+}
+
+bool gdbm_vpwtable_reader::rewind()
+{
+  if(dbf) {
+    key = gdbm_firstkey(dbf);
+    return true;
+  }
+  return false;
+}
+
+bool gdbm_vpwtable_reader::get(vpwentry& out)
+{
+  if(key.dptr) {
+    mystring name(key.dptr, key.dsize);
+    datum rec = gdbm_fetch(dbf, key);
+    mystring result(rec.dptr, rec.dsize);
+    free(rec.dptr);
+    if(!out.from_record(name, result))
+      return false;
+    key = gdbm_nextkey(dbf, key);
+    return true;
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/gdbm_vpwtable.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,35 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+#include "vdomain/vdomain.h"
+
+const mystring gdbm_extension = ".gdbm";
+
+vpwtable::vpwtable(const vdomain* d)
+  : filename(d->config.password_file() + gdbm_extension)
+{
+}
+
+vpwtable::vpwtable(const vpwtable& t)
+  : filename(t.filename)
+{
+}
+
+vpwtable::~vpwtable()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/reader.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,22 @@
+// Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include "vpwtable.h"
+
+vpwtable_reader::~vpwtable_reader()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/vpwtable/vpwtable.h	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,48 @@
+#ifndef VMAILMGR__VPWTABLE__H__
+#define VMAILMGR__VPWTABLE__H__
+
+#include "mystring/mystring.h"
+#include "misc/strlist.h"
+#include "vpwentry/vpwentry.h"
+
+class vdomain;
+
+class vpwtable_reader
+{
+public:
+  virtual ~vpwtable_reader();
+  virtual bool operator!() const = 0;
+  virtual bool get(vpwentry& out) = 0;
+  virtual bool rewind() = 0;
+  virtual bool end() = 0;
+};
+
+class vpwtable
+{
+private:
+  const mystring filename;
+  vpwtable();			// Unimplemented on purpose
+public:
+  vpwtable(const vdomain*);
+  vpwtable(const vpwtable&);
+  ~vpwtable();
+
+  vpwtable_reader* start_read() const;
+
+  vpwentry* getbyname(const mystring& name) const;
+  bool exists(const mystring& name) const;
+  
+  bool put(const vpwentry* vpw, bool onlyadd) const;
+
+  bool del(const mystring& name) const;
+  inline bool set(const vpwentry* vpw) const
+    {
+      return put(vpw, false);
+    }
+  inline bool add(const vpwentry* vpw) const
+    {
+      return put(vpw, true);
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/missing	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# 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
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing - GNU libit 0.0"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`configure.in'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`configure.in'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`configure.in'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f y.tab.h ]; then
+	echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  makeinfo)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequirements for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mkinstalldirs	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp"
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+  	  errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/php/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,3 @@
+php_DATA = vmail.inc
+EXTRA_DIST = vmail.features vmail.inc
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/php/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,210 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+php_DATA = vmail.inc
+EXTRA_DIST = vmail.features vmail.inc
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+DATA =  $(php_DATA)
+
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps php/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+install-phpDATA: $(php_DATA)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(phpdir)
+	@list='$(php_DATA)'; for p in $$list; do \
+	  if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(phpdir)/$$p"; \
+	    $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(phpdir)/$$p; \
+	  else if test -f $$p; then \
+	    echo " $(INSTALL_DATA) $$p $(DESTDIR)$(phpdir)/$$p"; \
+	    $(INSTALL_DATA) $$p $(DESTDIR)$(phpdir)/$$p; \
+	  fi; fi; \
+	done
+
+uninstall-phpDATA:
+	@$(NORMAL_UNINSTALL)
+	list='$(php_DATA)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(phpdir)/$$p; \
+	done
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = php
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-phpDATA
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-phpDATA
+uninstall: uninstall-am
+all-am: Makefile $(DATA)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(phpdir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: uninstall-phpDATA install-phpDATA tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/php/vmail.features	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,26 @@
+Features of using native PHP code for vmailmgr.
+
+- No need to compile PHP module, which few find themselves able to do.
+
+- Fully up to date as of 0.96.6, able to make use of all the new
+  functionality added (multiple forwarding destinations, users with forwarding
+  destinations and mailboxes, etc.)
+
+- User parsable listdomain output. Listdomain can be arranged however the
+  admin likes, allowing fields to be left out, reordered, or new fields
+  added (like a delete button).
+
+- Multiple commands per script, and user parsable output. While the python
+  CGI allows user parsable output, only the PHP functions can call more than
+  one function from the same page.
+
+- Only the PHP functions offer proper handling of multiple forwarding
+  desinations, allowing you to expand the number of fields on the HTML form
+  depending on the number of forwarding accounts already existing.
+
+- Easy to use interface, with good input checking. PHP commands are very
+  similar to the command line commands, and can accept all sorts of bad data
+  from user forms. New conditional failures can be easily added.
+  
+- Easily modified. The PHP commands are easy to add, extend, modify,
+  combine, update, etc.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/php/vmail.inc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,275 @@
+<?
+// Copyright (C) 2000 Mike Bell <mike@mikebell.org>
+//
+// Examples available at http://mailtest.mikebell.org/
+// Latest version will be included in each vmailmgr release
+//
+// 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 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+function vm_daemon_raw($arg)
+{
+        $vmailfile = "/tmp/.vmailmgrd";
+	if (file_exists("/etc/vmailmgr/socket-file"))
+		$socketfile = (file ("/etc/vmailmgr/socket-file"));
+	$socketfile = trim($socketfile[0]);
+	if ($socketfile != "")
+		$vmailfile = $socketfile;
+		
+
+        $vmailsock = fsockopen ($vmailfile, 0, $errno, $errstr, 4);
+	if (!$vmailsock) die("Failed to open socket file, is daemon running?");
+
+/*      Parse $arg, which should be an array of arguments to pass to the
+        daemon, into a glob consisting of each argument proceeded by a
+        two-byte representation of its length. */
+
+        for ($x=0; $x < sizeof($arg); $x++ )
+        {
+                $commandlength = strlen($arg[$x]);
+                $high=(($commandlength & (0xFF << 8)) >> 8);
+                $low=($commandlength & 0xFF);
+                $command .= sprintf("%c%c%s", $high, $low, $arg[$x]);
+        };
+
+
+/*      Create the header, which consists of another two byte length
+        representation, the number of arguments being passed, and the
+        command string created above. */
+
+        $args=$x-1;
+        $commandlength=strlen($command);
+        $high=(($commandlength & (255 << 8)) >> 8);
+        $low=($commandlength & 255);
+        $commandstr = sprintf("\002%c%c%c", $high, $low+1, $args).$command;
+
+/*      Pass it all to the daemon */
+
+        fputs($vmailsock, $commandstr);
+
+/*      Get the response        */
+
+	$value = ord( fgetc ($vmailsock));
+	$length = (ord(fgetc($vmailsock)) << 8) + ord(fgetc($vmailsock));
+
+	if ($length == 0) {
+		while (!feof($vmailsock))
+			$out=fread($vmailsock, 65535);
+		fclose($vmailsock);
+		return $out;
+	}
+
+	$message = fread ($vmailsock, $length);
+
+/*	Close the socket	*/
+	fclose($vmailsock);
+
+return array($value, $message);
+
+}
+
+function listdomain_parse_userdata($line, $username){
+	//Grab the protocol version
+	$ver=ord(substr($line, 0, 1));
+	if ($ver != 2) die("Protocol version is $ver, not the 2 as this script expects.");
+	//Chop off the version
+	$line=substr($line, 1);
+	//Grab the flags
+	while (substr($line, 0, 1) != chr(0)){
+		$flags[ord(substr($line, 0, 1))]=ord(substr($line, 1, 1));
+		$line=substr($line, 2);
+	};
+	//Explode the remainder into an array based on the NULs used to end the fields
+	$user=explode(chr(0), $line);
+	$x=1;
+	if ($user[$x++]!=("*")) $password="Set";
+	$mailbox=$user[$x++];
+	while($user[$x]!="")
+		$aliases[]=$user[$x++];
+	$x++;
+	$PersonalInfo=$user[$x++];
+	$HardQuota=$user[$x++];
+	$SoftQuota=$user[$x++];
+	$SizeLimit=$user[$x++];
+	$CountLimit=$user[$x++];
+	$CreationTime=$user[$x++];
+	$ExpiryTime=$user[$x++];
+	
+	return array($username, $password, $mailbox, $aliases,
+$PersonalInfo, $HardQuota, $SoftQuota, $SizeLimit, $CountLimit,
+$CreationTime, $ExpiryTime, $flags);
+}	
+
+/* Parses the lines from listdomain into fields. */
+
+function listdomain_parse_line($line){
+	//Grab the user's name
+	$data_position = strpos($line, chr(0));
+	$username=substr($line, 0, $data_position);
+	// Send that user's data to be parsed. The $username is nessesary because array manipulation in PHP3 is so limited.
+	return listdomain_parse_userdata(substr($line, $data_position+1), $username);
+}
+
+/* Does the ugly stuff for listdomain, and calls listdomain_parse_line once
+   for each user */
+
+function listdomain_parse($output){
+	$cur=1;
+	do {
+		$linelength=(ord(substr($output, $cur++, 1)) << 8 ) + ord(substr($output, $cur++, 1));
+		if ($linelength == 0) break;
+		$array[] = listdomain_parse_line(substr($output, $cur, $linelength));
+		$cur+=$linelength+1;
+	} while (1);
+	return $array;
+}
+
+/* listdomain, takes domain name and password, returns listdomain output
+   parsed as stated in listdomain_parse_userdata */
+
+function listdomain($domain, $password){
+if ($domain=="") return array(1, "Empty domain");
+if ($password=="") return array(1, "Empty domain password");
+	$command=array("listdomain",$domain, $password);
+	$temp=vm_daemon_raw(array("listdomain", $domain, $password));
+	if (is_array($temp)) return $temp;
+return listdomain_parse($temp);
+}
+
+/* Lookup, returns for a single virtual user what listdomain does for an entire domain. */
+
+function lookup($domain, $user, $password){
+	$command=array("lookup", $domain, $user, $password);
+	$tmp = vm_daemon_raw($command);
+	return listdomain_parse_userdata($tmp[1], $user);
+}
+			
+/* vadduser, takes domain name, password, username, userpassword, and an
+   array of forwarding desinations, returns an array consisting of an
+   integer exit code and message. */
+
+function vadduser($domain, $password, $username, $userpass, $forwards){
+if ($domain=="") return array(1, "Empty domain");
+if ($password=="") return array(1, "Empty domain password");
+if ($username=="") return array(1, "Empty username");
+if ($userpass=="") return array(1, "No user password supplied");
+	$command=array("adduser2", $domain, $username, $password,
+	               $userpass, $username);
+	for ($x=0; $x < sizeof($forwards); $x++)
+		if ($forwards[$x]!="") $command[]=$forwards[$x];
+return vm_daemon_raw($command);
+}
+
+/* vaddalias, takes domain name, password, username, userpassword, and an
+   array of forwarding desinations, returns an array consisting of an
+   integer exit code and message. If the user's password is left empty an
+   alias with no password will be created. */
+
+function vaddalias($domain, $password, $username, $userpass, $forwards){
+if ($domain=="") return array(1, "Empty domain");
+if ($password=="") return array(1, "Empty domain password");
+if ($username=="") return array(1, "Empty username");
+	$command=array("adduser2", $domain, $username, $password,
+	               $userpass, "");
+	for ($x=0; $x < sizeof($forwards); $x++)
+		if ($forwards[$x]!="")
+			$command[]=$forwards[$x];
+return vm_daemon_raw($command);
+}
+
+/* vdeluser, takes domain name, password, and username, returns an array
+   consisting of an integer exit code and message. */
+
+function vdeluser($domain, $password, $username){
+if ($domain=="") return array(1, "Empty domain");
+if ($password=="") return array(1, "Empty domain password");
+if ($username=="") return array(1, "Empty username");
+	$command=array("deluser", $domain, $username, $password);
+return vm_daemon_raw($command);
+}
+
+/* vchpass, takes domain name, password, username and a new password,
+   returns an array consisting of an integer exit code and message. Scripts
+   allowing users to change their own passwords should check the password
+   was entered correctly by having the user enter it twice and checking
+   these are equal*/
+
+function vchpass($domain, $password, $username, $newpass){
+if ($domain=="") return array(1, "Empty domain");
+if ($password=="") return array(1, "Empty domain password");
+if ($username=="") return array(1, "Empty username");
+if ($newpass=="") return array(1, "Empty new password");
+	$command=array("chattr", $domain, $username, $password, "1", $newpass);
+return vm_daemon_raw($command);
+}
+
+/* vchforward, takes domain name, password, username and an array of
+   forwarding addresses, returns an array consisting of an integer exit code
+   and message. */ 
+
+function vchforward($domain, $password, $username, $forwards){
+if ($domain=="") return array(1, "Empty domain");
+if ($password=="") return array(1, "Empty domain password");
+if ($username=="") return array(1, "Empty username");
+	$command=array("chattr", $domain, $username, $password, "2");
+	for ($x=0; $x< sizeof($forwards); $x++)
+		if ($forwards[$x] != "") $command[]=$forwards[$x];
+	if (sizeof($forwards) == 0) $command[] = "";
+return vm_daemon_raw($command);
+}
+
+/* v*/
+
+function vchattr($domain, $password, $username, $attr, $value){
+	$ATTR = array(
+		"PASS" => "1",
+		"DEST" => "2",
+		"HARDQUOTA" => "3",
+		"SOFTQUOTA" => "4",
+		"MSGSIZE" => "5",
+		"MSGCOUNT" => "6",
+		"EXPIRY" => "7",
+		"MAILBOX_ENABLED" => "8",
+		"PERSONAL" => "9"
+	);
+	$command = array ("chattr", $domain, $username, $password, $ATTR[$attr], $value);
+return vm_daemon_raw($command);
+}
+
+function vwriteautoresponse($domain, $password, $username, $message){
+	$command = array("autoresponse", $domain, $username, $password, "write", $message);
+	return vm_daemon_raw($command);
+}
+
+function vreadautoresponse($domain, $password, $username){
+	$command = array("autoresponse", $domain, $username, $password, "read");
+	return vm_daemon_raw($command);
+}
+
+function vdisableautoresponse($domain, $password, $username){
+	$command = array("autoresponse", $domain, $username, $password, "disable");
+	return vm_daemon_raw($command);
+}
+
+function venableautoresponse($domain, $password, $username){
+        $command = array("autoresponse", $domain, $username, $password, "enable");
+	return vm_daemon_raw($command);
+}
+
+function vautoresponsestatus($domain, $password, $username){
+	$command = array("autoresponse", $domain, $username, $password, "status");
+	return vm_daemon_raw($command);
+}
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,31 @@
+pythonlib_DATA = \
+	__init__.py __init__.pyc __init__.pyo \
+	commands.py commands.pyc commands.pyo \
+	config.py config.pyc config.pyo \
+	constants.py constants.pyc constants.pyo \
+	daemon.py daemon.pyc daemon.pyo \
+	local.py local.pyc local.pyo \
+	types.py types.pyc types.pyo
+EXTRA_DIST = __init__.py commands.py config.py constants.py daemon.py types.py
+CLEANFILES = local.py *.pyc *.pyo
+
+local.py: Makefile
+	echo "sysconfdir = '${sysconfdir}'" >$@
+
+__init__.pyc: __init__.py local.py
+__init__.pyo: __init__.py local.py
+commands.pyc: commands.py local.py
+commands.pyo: commands.py local.py
+config.pyc: config.py local.py
+config.pyo: config.py local.py
+constants.pyc: constants.py local.py
+constants.pyo: constants.py local.py
+daemon.pyc: daemon.py local.py
+daemon.pyo: daemon.py local.py
+types.pyc: types.py local.py
+types.pyo: types.py local.py
+
+.py.pyc:
+	python -c 'import $*'
+.py.pyo:
+	python -O -c 'import $*'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,238 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+pythonlib_DATA =  	__init__.py __init__.pyc __init__.pyo 	commands.py commands.pyc commands.pyo 	config.py config.pyc config.pyo 	constants.py constants.pyc constants.pyo 	daemon.py daemon.pyc daemon.pyo 	local.py local.pyc local.pyo 	types.py types.pyc types.pyo
+
+EXTRA_DIST = __init__.py commands.py config.py constants.py daemon.py types.py
+CLEANFILES = local.py *.pyc *.pyo
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DATA =  $(pythonlib_DATA)
+
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps python/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+install-pythonlibDATA: $(pythonlib_DATA)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(pythonlibdir)
+	@list='$(pythonlib_DATA)'; for p in $$list; do \
+	  if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pythonlibdir)/$$p"; \
+	    $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pythonlibdir)/$$p; \
+	  else if test -f $$p; then \
+	    echo " $(INSTALL_DATA) $$p $(DESTDIR)$(pythonlibdir)/$$p"; \
+	    $(INSTALL_DATA) $$p $(DESTDIR)$(pythonlibdir)/$$p; \
+	  fi; fi; \
+	done
+
+uninstall-pythonlibDATA:
+	@$(NORMAL_UNINSTALL)
+	list='$(pythonlib_DATA)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(pythonlibdir)/$$p; \
+	done
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = python
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-pythonlibDATA
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-pythonlibDATA
+uninstall: uninstall-am
+all-am: Makefile $(DATA)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(pythonlibdir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: uninstall-pythonlibDATA install-pythonlibDATA tags distdir \
+info-am info dvi-am dvi check check-am installcheck-am installcheck \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+local.py: Makefile
+	echo "sysconfdir = '${sysconfdir}'" >$@
+
+__init__.pyc: __init__.py local.py
+__init__.pyo: __init__.py local.py
+commands.pyc: commands.py local.py
+commands.pyo: commands.py local.py
+config.pyc: config.py local.py
+config.pyo: config.py local.py
+constants.pyc: constants.py local.py
+constants.pyo: constants.py local.py
+daemon.pyc: daemon.py local.py
+daemon.pyo: daemon.py local.py
+types.pyc: types.py local.py
+types.pyo: types.py local.py
+
+.py.pyc:
+	python -c 'import $*'
+.py.pyo:
+	python -O -c 'import $*'
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/__init__.py	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,1 @@
+from commands import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/commands.py	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,57 @@
+# Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+#
+# 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import daemon
+import string
+import types
+
+def execute(command, *args):
+    return daemon.execute(command, args)
+
+def check(domain, username, password):
+    return execute('check', domain, username, password)
+
+def listdomain(domain, password):
+    conn = daemon.Daemon()
+    response = conn.execute(daemon.Command('listdomain', (domain, password)))
+    users = []
+    while 1:
+        r = conn.read_response()
+        if not r:
+            break
+        (username,data) = string.split(r, '\0', 1)
+        users.append(types.NamedVUser(username, types.VUser(data)))
+    return users
+
+def adduser(domain, newuser, password, newpass, maildir=None, forwards=[]):
+    return daemon.execute('adduser2',
+                          (domain, newuser, password, newpass,
+                           maildir or '') + tuple(forwards))
+
+def lookup(domain, username, password):
+    return types.VUser(execute('lookup', domain, username, password))
+
+def autoresponse(domain, user, password, action, message=None):
+    cmd = [ domain, user, password, action ]
+    if message:
+        cmd.append(message)
+    return daemon.execute('autoresponse', cmd)
+
+def deluser(domain, username, password):
+    return execute('deluser', domain, username, password)
+
+def chattr(domain, username, password, attribute, *value):
+    return daemon.execute('chattr', (domain,username,password,attribute)+value)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/config.py	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,28 @@
+# Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+#
+# 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import os
+import string
+import local
+
+def read(name, default):
+    try:
+        file = open(os.path.join(vmailmgr_local.sysconfdir, name))
+        result = string.strip(file.readline())
+        file.close()
+    except:
+        result = default
+    return result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/constants.py	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,17 @@
+# Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+#
+# 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ATTR_MAILBOX_ENABLED = 8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/daemon.py	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,93 @@
+# Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+#
+# 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import config
+
+ok = 0
+bad = 1
+err = 2
+econn = 3
+
+class Bad(Exception):   pass
+class Error(Exception): pass
+class Econn(Exception): pass
+
+def encode_int(i):
+    return chr((i/256)%256) + chr(i%256)
+
+def encode_str(str):
+    return encode_int(len(str)) + str
+
+class Command:
+    def __init__(self, name, args):
+        self.name = name
+        self.args = args
+    
+    def encode(self):
+        argcount = len(self.args)
+        cmd = chr(argcount) + encode_str(self.name)
+        for i in range(argcount):
+            cmd = cmd + encode_str(self.args[i])
+        cmd = chr(2) + encode_int(len(cmd)) + cmd
+        return cmd
+
+class Daemon:
+    def __init__(self):
+        self.socket_file = config.read('socket-file', '/tmp/.vmailmgrd')
+        self.socket = None
+
+    def connect(self):
+        import socket
+        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        self.socket.connect(self.socket_file)
+
+    def read_response_noraise(self):
+        try:
+            reply = self.socket.recv(3)
+            code = ord(reply[0])
+            msglen = ord(reply[1])*256 + ord(reply[2])
+            message = self.socket.recv(msglen)
+        except:
+            return (econn, 'Server aborted the connection')
+        return (code, message)
+        
+    def read_response(self):
+        (code, message) = self.read_response_noraise()
+        if code == err:
+            raise Error, message
+        if code == bad:
+            raise Bad, message
+        if code == econn:
+            raise Econn, message
+        return message
+        
+    def execute(self, command):
+        try:
+            self.connect()
+        except:
+            raise Econn, "Unable to connect to the server"
+        data = command.encode()
+        try:
+            self.socket.send(data)
+        except:
+            raise Econn, "Server aborted the connection"
+        # Don't close the socket here -- it will be closed
+        # as soon as it gets garbage collected, and remains
+        # usable for other commands like listdomain.
+        return self.read_response()
+
+def execute(command, args):
+    return Daemon().execute(Command(command, args))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/types.py	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,141 @@
+# Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+#
+# 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import string
+import time
+
+class Limit:
+    unlimited = -1
+    def __init__(self, str):
+        if str[0] == '-' or string.lower(str) == 'unlimited':
+            str = self.unlimited
+        self.value = int(str)
+    def __str__(self):
+        if self.value == self.unlimited:
+            return 'unlimited'
+        return str(self.value)
+    def __repr__(self):
+        if self.value == self.unlimited:
+            val = '-'
+        else:
+            val = str(self.value)
+        return "Limit('%s')" % val
+
+class Flag:
+    def __init__(self, value):
+        self.value = value
+    def __str__(self):
+        if self.value:
+            return 'true'
+        return 'false'
+    def __repr__(self):
+        return "Flag(%s)" % repr(self.value)
+    def html(self, fieldname):
+        if self.value:
+            strue = ' selected'
+            sfalse = ''
+        else:
+            strue = ''
+            sfalse = ' selected'
+        return ("<select name='%s'>"
+                "<option value=1%s>True"
+                "<option value=0%s>False"
+                "</select>" % ( fieldname, strue, sfalse ) )
+
+class Time:
+    def __init__(self, value):
+        self.time = int(value)
+    def __str__(self):
+        return time.asctime(time.localtime(self.time))
+    def __repr__(self):
+        return 'Time(%d)' % self.time
+
+ATTR_MAILBOX_ENABLED = 8
+
+class VUser:
+    # Default values
+    mailbox_enabled = 1
+    password = ''
+    mailbox = ''
+    forwards = []
+    personal = ''
+    hard_quota = -1
+    soft_quota = -1
+    message_size_limit = -1
+    message_count_limit = -1
+    creation_time = 0
+    expiry_time = -1
+    
+    def __init__(self, bin=None):
+        if bin:
+            self.from_binary(bin)
+
+    def from_binary(self, bin):
+        if bin[0] <> chr(2):
+            raise ValueError, "Virtual user data has invalid format number"
+        i = 1
+        while bin[i] <> chr(0):
+            flag = ord(bin[i])
+            val = ord(bin[i+1])
+            i = i + 2
+            if flag == ATTR_MAILBOX_ENABLED:
+                self.mailbox_enabled = Flag(val)
+            else:
+                raise ValueError, "Invalid flag number %d in vuser data" % flag
+        bin = string.split(bin[i+1:], '\0')
+        self.password = bin[0]
+        self.mailbox = bin[1]
+        self.forwards = []
+        i = 2
+        while bin[i]:
+            self.forwards.append(bin[i])
+            i = i + 1
+        self.personal = bin[i+1]
+        self.hard_quota = Limit(bin[i+2])
+        self.soft_quota = Limit(bin[i+3])
+        self.message_size_limit = Limit(bin[i+4])
+        self.message_count_limit = Limit(bin[i+5])
+        self.creation_time = Time(bin[i+6])
+        self.expiry_time = Limit(bin[i+7])
+
+    def __getitem__(self, key):
+        """Allow subscript access to the attributes of this object.
+
+        This method allows the data in the virtual user to be
+        accessed as though it were a dictionary.  This allows the use of
+        such expressions as '%(mailbox)s'%user."""
+        return getattr(self, key)
+
+    def keys(self): return self.__dict__.keys()
+    def values(self): return self.__dict__.values()
+    def items(self): return self.__dict__.items()
+    def dict(self): return self.__dict__
+
+class NamedVUser:
+    def __init__(self, username, vuser):
+        self.username = username
+        self.vuser = vuser
+    def __cmp__(self, other):
+        return cmp(self.username, other.username)
+    def __getitem__(self, key):
+        if key == 'username':
+            return self.username
+        else:
+            return self.vuser[key]
+    def dict(self):
+        d = self.vuser.dict()
+        d['username'] = self.username
+        return d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/Makefile.am	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,4 @@
+EXTRA_DIST = autoresponder.sh \
+	vmailmgrd.init \
+	vmailmgrd.run \
+	vmailmgrd-log.run
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/Makefile.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,188 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+CDBPROGS = @CDBPROGS@
+CDBSCRIPTS = @CDBSCRIPTS@
+CXX = @CXX@
+HTML2TXT = @HTML2TXT@
+LN = @LN@
+LYNX = @LYNX@
+MAKEINFO = @MAKEINFO@
+MKDIR = @MKDIR@
+PACKAGE = @PACKAGE@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+RM = @RM@
+STRIP = @STRIP@
+SUFFIXES = @SUFFIXES@
+VERSION = @VERSION@
+W3M = @W3M@
+cgidir = @cgidir@
+phpdir = @phpdir@
+pythonlibdir = @pythonlibdir@
+
+EXTRA_DIST = autoresponder.sh 	vmailmgrd.init 	vmailmgrd.run 	vmailmgrd-log.run
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: @SUFFIXES@
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps scripts/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = scripts
+
+distdir: $(DISTFILES)
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: tags distdir info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/autoresponder.sh	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# This script checks for the presence of an autoresponse message, and if
+# present executes the autoresponder.
+#
+# To use this autoresponder, copy this file to
+# vmailmgr/vdeliver-postdeliver if it does not already exist.  If it
+# exists, copy this file somewhere accessable and add a call to it to
+# vmailmgr/vdeliver-postdeliver.
+#
+# The autoresponder used here can be found at:
+#	http://em.ca/~bruceg/qmail-autoresponder/
+#
+
+if test -s $MAILDIR/autoresponse/message.txt
+then
+  qmail-autoresponder $MAILDIR/autoresponse/message.txt $MAILDIR/autoresponse
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/vmailmgrd-log.run	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec multilog t /var/log/vmailmgrd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/vmailmgrd.init	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# vmailmgrd	This shell script takes care of starting and stopping
+#		vmailmgrd (virtual mail manager daemon)
+#
+# chkconfig: 345 65 35
+# description: vmailmgrd is the daemon required for the vmailmgr package
+# to work properly.
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# See how we were called.
+case "$1" in
+  start)
+	svc-start vmailmgrd
+        ;;
+  stop)
+	svc-stop vmailmgrd
+        ;;
+  status)
+	svc-status vmailmgrd
+	;;
+  restart)
+	"$0" stop
+	sleep 1
+	"$0" start
+	;;
+  *)
+        echo "Usage: vmailmgrd {start|stop|restart|status}"
+        exit 1
+esac
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/vmailmgrd.run	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,9 @@
+#!/bin/sh
+umask 0
+if [ -s /etc/vmailmgr/socket-file ]; then
+  socket_file="`head -1 /etc/vmailmgr/socket-file`"
+else
+  socket_file=/tmp/.vmailmgrd
+fi
+
+exec unixserver -v -- $socket_file vmailmgrd -D -V 2>&1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stamp-h.in	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,1 @@
+timestamp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vmailmgr-0.96.9.spec	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,152 @@
+Name: vmailmgr
+Version: 0.96.9
+Release: 1
+Group: Utilities/System
+URL: http://www.vmailmgr.org/
+Copyright: GPL
+Source: http://www.vmailmgr.org/archive/%{PACKAGE_VERSION}/vmailmgr-%{PACKAGE_VERSION}.tar.gz
+Summary: Simple virtualizing POP3 password interface
+Packager: Bruce Guenter <bruceg@em.ca>
+Buildroot: /tmp/vmailmgr
+Obsoletes: checkvpw
+
+%description
+Vmailmgr provides a virtualizing password-checking interface to
+qmail-pop3d as well as both a delivery agent to automatically delivery
+mail within a virtual domain and a set of tools to manage such a domain.
+
+%package cgi
+Summary: CGI applications for vmailmgr
+Group: Utilities/System
+Requires: vmailmgr-daemon = %{PACKAGE_VERSION}
+%description cgi
+This package contains CGI applications to allow web-based administration
+of vmailmgr systems.
+
+%package courier-imap
+Summary: Vmailmgr authentication module for Courier IMAP
+Requires: courier-imap
+Group: Utilities/System
+%description courier-imap
+This package contains the vmailmgr authentication module to be used by
+Courier IMAP.
+
+%package daemon
+Summary: Vmailmgr daemon for CGIs
+Requires: supervise-scripts >= 2.2
+Requires: ucspi-unix
+Group: Utilities/System
+%description daemon
+This package contains the vmailmgrd daemon that provides virtual domain
+manipulation services to support unprivileged clients like CGIs.
+
+%package php
+Summary: PHP include files
+Group: Development/Libraries
+%description php
+This package contains the include files necessary to call VMailMgr
+functions from PHP.
+
+%package python
+Summary: Python library for accessing VMailMgr
+Group: Development/Libraries
+Requires: python >= 1.5
+%description python
+This package contains the Python library code necessary to call VMailMgr
+
+%prep
+%setup
+CFLAGS="$RPM_OPT_FLAGS" \
+CXXFLAGS="$RPM_OPT_FLAGS" \
+LDFLAGS="-s" \
+./configure --prefix=/usr
+
+%build
+make all
+make all
+
+%install
+rm -rf $RPM_BUILD_ROOT
+for dir in var/service/vmailmgrd/log var/log/vmailmgrd \
+	etc/rc.d/init.d etc/rc.d/rc{0,1,2,3,4,5,6}.d etc/vmailmgr
+do
+	mkdir -p $RPM_BUILD_ROOT/$dir
+done
+make	prefix=$RPM_BUILD_ROOT/usr \
+	cgidir=$RPM_BUILD_ROOT/home/httpd/cgi-bin \
+	pythonlibdir=$RPM_BUILD_ROOT/usr/lib/python1.5/vmailmgr \
+	phpdir=$RPM_BUILD_ROOT/home/httpd/php \
+	install-strip
+install -m 755 scripts/vmailmgrd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/vmailmgrd
+install -m 755 scripts/vmailmgrd.run $RPM_BUILD_ROOT/var/service/vmailmgrd/run
+install -m 755 scripts/vmailmgrd-log.run $RPM_BUILD_ROOT/var/service/vmailmgrd/log/run
+pushd $RPM_BUILD_ROOT/etc/rc.d
+ln -s ../init.d/vmailmgrd rc0.d/K35vmailmgrd
+ln -s ../init.d/vmailmgrd rc1.d/K35vmailmgrd
+ln -s ../init.d/vmailmgrd rc2.d/S65vmailmgrd
+ln -s ../init.d/vmailmgrd rc3.d/S65vmailmgrd
+ln -s ../init.d/vmailmgrd rc4.d/S65vmailmgrd
+ln -s ../init.d/vmailmgrd rc5.d/S65vmailmgrd
+ln -s ../init.d/vmailmgrd rc6.d/K35vmailmgrd
+popd
+pushd $RPM_BUILD_ROOT/etc/vmailmgr
+echo users >user-dir
+echo passwd >password-file
+echo ./Maildir/ >default-maildir
+echo maildir >maildir-arg-str
+echo /var/service/vmailmgrd/socket >socket-file
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+if [ $# -eq 2 -a -f /etc/vmailmgr.conf ]; then
+  vconf2dir /etc/vmailmgr.conf /etc/vmailmgr
+fi
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS ChangeLog COPYING NEWS TODO doc/ChangeLog* doc/YEAR2000
+%doc doc/*.txt */*.html doc/*.sgml
+%doc scripts/autoresponder.sh
+%dir /etc/vmailmgr
+%config(missingok,noreplace) %verify(user,group,mode) /etc/vmailmgr/*
+/usr/bin/*
+/usr/man/man1/*
+/usr/man/man7/*
+/usr/man/man8/*
+
+%files cgi
+%defattr(-,root,root)
+%doc cgi/*.html
+/home/httpd/cgi-bin/listvdomain
+/home/httpd/cgi-bin/vaddalias
+/home/httpd/cgi-bin/vadduser
+/home/httpd/cgi-bin/vchattr
+/home/httpd/cgi-bin/vchforwards
+/home/httpd/cgi-bin/vdeluser
+/home/httpd/cgi-bin/vpasswd
+
+%files courier-imap
+%defattr(-,root,root)
+/usr/lib/courier-imap/libexec/authlib/*
+
+%files daemon
+%defattr(-,root,root)
+%config /etc/rc.d/init.d/vmailmgrd
+%config /etc/rc.d/rc?.d/*vmailmgrd
+/usr/sbin/vmailmgrd
+%attr(1755,root,root) %dir /var/service/vmailmgrd
+%dir /var/service/vmailmgrd/log
+/var/service/vmailmgrd/log/run
+/var/service/vmailmgrd/run
+%attr(0700,root,root) /var/log/vmailmgrd
+
+%files php
+%defattr(-,root,root)
+%doc php/vmail.features
+/home/httpd/php/*
+
+%files python
+%defattr(-,root,root)
+/usr/lib/python1.5/vmailmgr