diff -Naur cvs-1.12.13.1/ChangeLog cvs-1.12.13.1.new/ChangeLog
--- cvs-1.12.13.1/ChangeLog	2006-09-25 16:08:19.000000000 +0530
+++ cvs-1.12.13.1.new/ChangeLog	2006-10-12 16:12:26.000000000 +0530
@@ -1,3 +1,7 @@
+2006-10-12  PJP <prasad@ncb.ernet.in>
+
+    * NEWS: Note 'cvs passwd' new command introduced.
+
 2006-09-25  Mark D. Baushke  <mdb@gnu.org>
 
 	* config.h.in, configure: Regenerated.
diff -Naur cvs-1.12.13.1/configure cvs-1.12.13.1.new/configure
--- cvs-1.12.13.1/configure	2006-09-25 16:08:19.000000000 +0530
+++ cvs-1.12.13.1.new/configure	2006-10-13 10:27:27.000000000 +0530
@@ -41648,8 +41648,10 @@
 for ac_func in \
 	fchdir \
 	fchmod \
+	flockfile \
 	fsync \
 	ftime \
+	funlockfile \
 	geteuid \
 	getgroups \
 	getpagesize \
diff -Naur cvs-1.12.13.1/configure.in cvs-1.12.13.1.new/configure.in
--- cvs-1.12.13.1/configure.in	2006-09-22 23:24:38.000000000 +0530
+++ cvs-1.12.13.1.new/configure.in	2006-10-13 10:24:04.000000000 +0530
@@ -262,8 +262,10 @@
 AC_CHECK_FUNCS(\
 	fchdir \
 	fchmod \
+	flockfile \
 	fsync \
 	ftime \
+	funlockfile \
 	geteuid \
 	getgroups \
 	getpagesize \
diff -Naur cvs-1.12.13.1/doc/ChangeLog cvs-1.12.13.1.new/doc/ChangeLog
--- cvs-1.12.13.1/doc/ChangeLog	2006-09-13 02:00:25.000000000 +0530
+++ cvs-1.12.13.1.new/doc/ChangeLog	2006-10-12 16:17:30.000000000 +0530
@@ -1,3 +1,8 @@
+2006-10-12  PJP <prasad@ncb.ernet.in>
+
+    * cvs.texinfo (passwd): edited to add description for new 'passwd' command
+    * cvsclient.texi (passwd): edited to describe the protocol used by 'passwd'
+
 2006-09-12  Derek Price  <derek@ximbiot.com>
 
 	* cvs.texinfo (commitinfo): Describe new %T flag.
diff -Naur cvs-1.12.13.1/doc/cvs.1 cvs-1.12.13.1.new/doc/cvs.1
--- cvs-1.12.13.1/doc/cvs.1	2006-08-22 03:04:05.000000000 +0530
+++ cvs-1.12.13.1.new/doc/cvs.1	2007-03-09 17:21:07.000000000 +0530
@@ -3588,6 +3588,77 @@
 .IP "" 2
 Show files from date.
 .SP
+.SH "passwd"
+.SS "- Change your cvs password"
+.IX "passwd(subcommand)"
+.SP
+.IP "\(bu" 2
+Synopsis: passwd [-a] [-D domain] [-e] [-r real_user] [-R] [-x] 
+              [-X] [username]
+.IP "\(bu" 2
+Requires: repository
+.IP "\(bu" 2
+Changes: an admin file(CVSROOT/passwd) 
+.IP "\(bu" 2
+Synonym: setpass
+.SP
+\fBpasswd\fR lets you change your cvs password or manipulate cvs user accounts
+using the regular cvs command line client. At present it supports changing only pserver password.
+.SP
+.SS "OPTIONS"
+The following options are supported by \(aqpasswd\(aq. Please note that, in case, when
+multiple options are supplied, they are treated in a sequence, as listed below
+.SP
+.IP "" 0
+\fB-a\fR
+.IP "" 2
+Add new user. This option allows the cvs administrator to add a new user entry
+to the CVSROOT/passwd file, thus creating a new cvs user. It is a restricted
+operation, and only cvs administrator can perform this.
+.IP "" 0
+\fB-D domain\fR
+.IP "" 2
+Specify users\(aq domain password, instead of seperate cvs password. It can be used
+with the cvs server such as CVSNT. Please note that, it is not supported by this
+cvs server.
+.IP "" 0
+\fB-e\fR
+.IP "" 2
+Enable local encrypt; this makes cvs client to encrypt the password
+using md5 based algorithm (see crypt(3)), then scramble the
+message and send it over the wire. Be informed that, this 
+will prevent cvs server from doing the encryption.
+.IP "" 0
+\fB-r real_user\fR
+.IP "" 2
+Specify the real system username. This is the user, whose account is used when
+the cvs(pserver) user login to the system(using \(aqcvs login\(aq). It is a restricted
+operation.
+.IP "" 0
+\fB-R\fR
+.IP "" 2
+Remove the (above)system user alias for the cvs user. It is a restricted
+operation.
+.IP "" 0
+\fB-x\fR
+.IP "" 2
+Disable cvs user. This is done so as to prohibit the subject from using the cvs
+system. It is a restricted operation.
+.IP "" 0
+\fB-X\fR
+.IP "" 2
+Delete cvs user. Remove the users\(aq entry from the CVSROOT/passwd file forever.
+It is a restricted operation.
+.SP
+.SS "Security "
+First of all, be assured that, password never flows in clear
+text form over the wire. It is always scrambled using the
+cvs\(aq native scramble() function.
+.SP
+Secondly, \fBpasswd\fR when invoked with \(aq-e\(aq flag, as
+explained above, password is encrypted and then scrambled by
+cvs client, before sending it over to the cvs server.
+.SP
 .SH "rls examples"
 .SP
 .PD 0
diff -Naur cvs-1.12.13.1/doc/cvsclient.texi cvs-1.12.13.1.new/doc/cvsclient.texi
--- cvs-1.12.13.1/doc/cvsclient.texi	2006-08-26 06:51:20.000000000 +0530
+++ cvs-1.12.13.1.new/doc/cvsclient.texi	2007-03-09 17:17:25.000000000 +0530
@@ -1195,6 +1195,35 @@
 same argument as the user being selected.
 @end table
 
+@item passwd \n
+Response expected: yes. Update @code{CVSROOT/passwd} file with given username 
+and password. @code{passwd} request facilitates user to change her pserver
+password and to manipulate cvs users accounts using regular cvs command line 
+client. Here is how @code{passwd} works
+
+Cvs client receives the user input as command line arguments, shown below 
+
+@code{cvs passwd [-a] [-D domain] [-e] [-r real_user] [-R] [-x] [-X]
+                [username]}
+
+The options are sent to the server as received, but when password has to be
+sent, the new password is first scrambled using cvs' native scramble()
+function, and then is sent over to the server. The cvs client sends the
+current password to the server along with the new one; But only after making
+it sure that, the cvs server supports authenticating the current password,
+otherwise, it wouldn't send it.
+
+On the server side, cvs server receives the above message as 
+
+@code{cvs server [-a] [-D domain] [-e] [-r real_user] [-R] [-x] [-X]
+                username [current password] [new password]}
+
+The server then descrambles the message(if required), extracts the username
+and password(s) or other information from the message, and according to the
+options does the necessary changes to CVSROOT/passwd file. If the current
+password is supplied, the server first authenticates the user, and if
+successful, then proceeds with the requested changes.
+
 @item co \n
 Response expected: yes.  Get files from the repository.  This uses any
 previous @code{Argument}, @code{Directory}, @code{Entry}, or
diff -Naur cvs-1.12.13.1/doc/cvs.texinfo cvs-1.12.13.1.new/doc/cvs.texinfo
--- cvs-1.12.13.1/doc/cvs.texinfo	2006-09-13 02:00:25.000000000 +0530
+++ cvs-1.12.13.1.new/doc/cvs.texinfo	2007-03-09 16:30:24.000000000 +0530
@@ -8259,6 +8259,7 @@
 * import::                      Import sources into CVS, using vendor branches
 * log & rlog::                  Show log messages for files
 * ls & rls::                    List files in the repository
+* passwd::                      Change your cvs password
 * rdiff::                       'patch' format diffs between releases
 * release::                     Indicate that a directory is no longer in use
 * remove::                      Remove files from active development
@@ -11452,6 +11453,68 @@
 Show files from date.
 @end table
 
+@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+@node passwd
+@appendixsec passwd - Change your cvs password
+@cindex passwd(subcommand)
+
+@itemize @bullet
+@item
+Synopsis: passwd [-a] [-D domain] [-e] [-r real_user] [-R] [-x] 
+              [-X] [username]
+@item
+Requires: repository
+@item
+Changes: an admin file(CVSROOT/passwd) 
+@item
+Synonym: setpass
+@end itemize
+
+@code{passwd} lets you change your cvs password or manipulate cvs user accounts
+using the regular cvs command line client. At present it supports changing only pserver password.
+
+@appendixsubsec OPTIONS
+The following options are supported by 'passwd'. Please note that, in case, when
+multiple options are supplied, they are treated in a sequence, as listed below
+
+@table @code
+@item -a
+Add new user. This option allows the cvs administrator to add a new user entry
+to the CVSROOT/passwd file, thus creating a new cvs user. It is a restricted
+operation, and only cvs administrator can perform this.
+@item -D domain
+Specify users' domain password, instead of seperate cvs password. It can be used
+with the cvs server such as CVSNT. Please note that, it is not supported by this
+cvs server.
+@item -e
+Enable local encrypt; this makes cvs client to encrypt the password
+using md5 based algorithm (see crypt(3)), then scramble the
+message and send it over the wire. Be informed that, this 
+will prevent cvs server from doing the encryption.
+@item -r real_user
+Specify the real system username. This is the user, whose account is used when
+the cvs(pserver) user login to the system(using 'cvs login'). It is a restricted
+operation.
+@item -R
+Remove the (above)system user alias for the cvs user. It is a restricted
+operation.
+@item -x
+Disable cvs user. This is done so as to prohibit the subject from using the cvs
+system. It is a restricted operation.
+@item -X
+Delete cvs user. Remove the users' entry from the CVSROOT/passwd file forever.
+It is a restricted operation.
+@end table
+
+@appendixsubsec Security 
+First of all, be assured that, password never flows in clear
+text form over the wire. It is always scrambled using the
+cvs' native scramble() function.
+
+Secondly, @code{passwd} when invoked with '-e' flag, as
+explained above, password is encrypted and then scrambled by
+cvs client, before sending it over to the cvs server.
+
 @c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 @node rls examples
 @appendixsubsec rls examples
@@ -12920,6 +12983,27 @@
 @ref{Password authentication client}.
 
 @c ------------------------------------------------------------
+@item passwd [@var{options}]
+Change your cvs password
+
+@table @code
+@item -a
+Add user
+@item -D domain
+Use domain password (Win32 only)
+@item -e
+Enable local encrypt. See @ref{passwd}.
+@item -r
+Alias to real system user
+@item -R
+Remove alias to real system user
+@item -x
+Disable user
+@item -X
+Delete user  See @ref{passwd}.
+@end table
+
+@c ------------------------------------------------------------
 @item pserver
 Password authenticated server.
 See @ref{Password authentication server}.
diff -Naur cvs-1.12.13.1/doc/stamp-1 cvs-1.12.13.1.new/doc/stamp-1
--- cvs-1.12.13.1/doc/stamp-1	2007-03-12 16:42:34.000000000 +0530
+++ cvs-1.12.13.1.new/doc/stamp-1	2007-03-12 16:31:18.000000000 +0530
@@ -1,4 +1,4 @@
-@set UPDATED 26 August 2006
-@set UPDATED-MONTH August 2006
+@set UPDATED 9 March 2007
+@set UPDATED-MONTH March 2007
 @set EDITION 1.12.13.1
 @set VERSION 1.12.13.1
diff -Naur cvs-1.12.13.1/doc/stamp-vti cvs-1.12.13.1.new/doc/stamp-vti
--- cvs-1.12.13.1/doc/stamp-vti	2007-03-12 16:42:34.000000000 +0530
+++ cvs-1.12.13.1.new/doc/stamp-vti	2007-03-12 16:31:18.000000000 +0530
@@ -1,4 +1,4 @@
-@set UPDATED 13 September 2006
-@set UPDATED-MONTH September 2006
+@set UPDATED 9 March 2007
+@set UPDATED-MONTH March 2007
 @set EDITION 1.12.13.1
 @set VERSION 1.12.13.1
diff -Naur cvs-1.12.13.1/doc/version-client.texi cvs-1.12.13.1.new/doc/version-client.texi
--- cvs-1.12.13.1/doc/version-client.texi	2007-03-12 16:42:34.000000000 +0530
+++ cvs-1.12.13.1.new/doc/version-client.texi	2007-03-12 16:31:18.000000000 +0530
@@ -1,4 +1,4 @@
-@set UPDATED 26 August 2006
-@set UPDATED-MONTH August 2006
+@set UPDATED 9 March 2007
+@set UPDATED-MONTH March 2007
 @set EDITION 1.12.13.1
 @set VERSION 1.12.13.1
diff -Naur cvs-1.12.13.1/doc/version.texi cvs-1.12.13.1.new/doc/version.texi
--- cvs-1.12.13.1/doc/version.texi	2007-03-12 16:42:34.000000000 +0530
+++ cvs-1.12.13.1.new/doc/version.texi	2007-03-12 16:31:18.000000000 +0530
@@ -1,4 +1,4 @@
-@set UPDATED 13 September 2006
-@set UPDATED-MONTH September 2006
+@set UPDATED 9 March 2007
+@set UPDATED-MONTH March 2007
 @set EDITION 1.12.13.1
 @set VERSION 1.12.13.1
diff -Naur cvs-1.12.13.1/NEWS cvs-1.12.13.1.new/NEWS
--- cvs-1.12.13.1/NEWS	2006-09-13 02:01:17.000000000 +0530
+++ cvs-1.12.13.1.new/NEWS	2006-10-10 12:56:03.000000000 +0530
@@ -23,6 +23,9 @@
 * When UseNewInfoFmtStrings is enabled, the %{vV} formats will now
   expose the real version instead of NONE for removed files.
 
+* cvs 'passwd' new command introduced. It facilitates cvs user account 
+  management for the pserver mode.
+  
 BUG FIXES
 
 * Applying diffs when checking out very old revisions has been reduced from an
diff -Naur cvs-1.12.13.1/src/ChangeLog cvs-1.12.13.1.new/src/ChangeLog
--- cvs-1.12.13.1/src/ChangeLog	2006-09-22 06:02:48.000000000 +0530
+++ cvs-1.12.13.1.new/src/ChangeLog	2006-10-12 16:48:59.000000000 +0530
@@ -1,3 +1,22 @@
+2005-10-12  PJP <prasad@ncb.ernet.in>
+
+    * passwd.c: new file, part of the cvs-passwd patch. Adds 'passwd'
+    command to the cvs. This will let the user to change her cvs password,
+    and cvs admin to do the user account management.
+
+    * passwd.h: new file, part of the cvs-passwd patch. Header for
+    passwd.c
+
+    * main.c (cmds[], cmd_usage[]): entry for 'passwd' is made.
+    
+    * server.c (requests[]): entry for 'passwd' is made. Also a function
+    serve_passwd() to call spasswd() is added.
+
+    * Makefile.am (cvs_SOURCES): add passwd.[ch] 
+    
+    * Makefile.in (cvs_SOURCES, am_cvs_OBJECTS): add passwd.[ch], and
+    passwd.$(OBJEXT).
+
 2006-09-21  Mark D. Baushke  <mdb@gnu.org>
 
 	* commit.c (commit_fileproc): If support for the old info format
diff -Naur cvs-1.12.13.1/src/hash.h cvs-1.12.13.1.new/src/hash.h
--- cvs-1.12.13.1/src/hash.h	2006-08-19 21:12:19.000000000 +0530
+++ cvs-1.12.13.1.new/src/hash.h	2006-09-28 16:06:53.000000000 +0530
@@ -28,7 +28,7 @@
 {
     NT_UNKNOWN, HEADER, ENTRIES, FILES, LIST, RCSNODE,
     RCSVERS, DIRS, UPDATE, LOCK, NDBMNODE, FILEATTR,
-    VARIABLE, RCSFIELD, RCSCMPFLD, RCSSTRING
+    VARIABLE, RCSFIELD, RCSCMPFLD, RCSSTRING, PASSWDNODE
 };
 typedef enum ntype Ntype;
 
diff -Naur cvs-1.12.13.1/src/main.c cvs-1.12.13.1.new/src/main.c
--- cvs-1.12.13.1/src/main.c	2006-05-17 20:54:30.000000000 +0530
+++ cvs-1.12.13.1.new/src/main.c	2006-10-20 14:15:41.000000000 +0530
@@ -30,6 +30,7 @@
 /* CVS Headers.  */
 #include "command_line_opt.h"
 #include "gpg.h"
+#include "passwd.h"
 #include "sign.h"
 #include "verify.h"
 
@@ -177,6 +178,7 @@
 #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
     { "pserver",  NULL,       NULL,        server,    CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
 #endif
+    { "passwd",	  "password", "setpass",   passwd,    CVS_CMD_MODIFIES_REPOSITORY },
     { "rannotate","rann",     "ra",        annotate,  0 },
     { "rdiff",    "patch",    "pa",        patch,     0 },
     { "release",  "re",       "rel",       release,   CVS_CMD_MODIFIES_REPOSITORY },
@@ -269,6 +271,7 @@
     "        logout       Removes entry in .cvspass for remote repository\n",
 #endif /* AUTH_CLIENT_SUPPORT */
     "        ls           List files available from CVS\n",
+    "        passwd       Change your cvs password\n"
 #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
     "        pserver      Password server mode\n",
 #endif
diff -Naur cvs-1.12.13.1/src/Makefile.am cvs-1.12.13.1.new/src/Makefile.am
--- cvs-1.12.13.1/src/Makefile.am	2006-07-07 04:14:57.000000000 +0530
+++ cvs-1.12.13.1.new/src/Makefile.am	2006-09-26 11:52:51.000000000 +0530
@@ -68,6 +68,7 @@
 	myndbm.c \
 	no_diff.c no_diff.h \
 	parseinfo.c parseinfo.h \
+	passwd.c passwd.h \
 	patch.c \
 	rcs.c \
 	rcscmds.c \
diff -Naur cvs-1.12.13.1/src/Makefile.in cvs-1.12.13.1.new/src/Makefile.in
--- cvs-1.12.13.1/src/Makefile.in	2006-09-22 23:24:41.000000000 +0530
+++ cvs-1.12.13.1.new/src/Makefile.in	2006-10-10 14:15:31.000000000 +0530
@@ -159,15 +159,16 @@
 	log-buffer.$(OBJEXT) login.$(OBJEXT) logmsg.$(OBJEXT) \
 	ls.$(OBJEXT) main.$(OBJEXT) mkmodules.$(OBJEXT) \
 	modules.$(OBJEXT) ms-buffer.$(OBJEXT) myndbm.$(OBJEXT) \
-	no_diff.$(OBJEXT) parseinfo.$(OBJEXT) patch.$(OBJEXT) \
-	rcs.$(OBJEXT) rcscmds.$(OBJEXT) recurse.$(OBJEXT) \
-	release.$(OBJEXT) remove.$(OBJEXT) repos.$(OBJEXT) \
-	root.$(OBJEXT) rsh-client.$(OBJEXT) run.$(OBJEXT) \
-	scramble.$(OBJEXT) server.$(OBJEXT) sign.$(OBJEXT) \
-	stack.$(OBJEXT) status.$(OBJEXT) subr.$(OBJEXT) tag.$(OBJEXT) \
-	update.$(OBJEXT) verify.$(OBJEXT) version.$(OBJEXT) \
-	vers_ts.$(OBJEXT) watch.$(OBJEXT) wrapper.$(OBJEXT) \
-	zlib.$(OBJEXT)
+	no_diff.$(OBJEXT) parseinfo.$(OBJEXT) passwd.$(OBJEXT) \
+    patch.$(OBJEXT) rcs.$(OBJEXT) rcscmds.$(OBJEXT) \
+    recurse.$(OBJEXT) release.$(OBJEXT) remove.$(OBJEXT) \
+    repos.$(OBJEXT) root.$(OBJEXT) rsh-client.$(OBJEXT) \
+    run.$(OBJEXT) scramble.$(OBJEXT) server.$(OBJEXT) \
+    sign.$(OBJEXT) stack.$(OBJEXT) status.$(OBJEXT) \
+    subr.$(OBJEXT) tag.$(OBJEXT) update.$(OBJEXT) \
+    verify.$(OBJEXT) version.$(OBJEXT) vers_ts.$(OBJEXT) \
+    watch.$(OBJEXT) wrapper.$(OBJEXT) zlib.$(OBJEXT)
+
 cvs_OBJECTS = $(am_cvs_OBJECTS)
 am__DEPENDENCIES_1 =
 binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
@@ -422,6 +423,7 @@
 	myndbm.c \
 	no_diff.c no_diff.h \
 	parseinfo.c parseinfo.h \
+	passwd.c passwd.h \
 	patch.c \
 	rcs.c \
 	rcscmds.c \
@@ -621,6 +623,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/myndbm.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/no_diff.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parseinfo.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/passwd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patch.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcs.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcscmds.Po@am__quote@
diff -Naur cvs-1.12.13.1/src/passwd.c cvs-1.12.13.1.new/src/passwd.c
--- cvs-1.12.13.1/src/passwd.c	1970-01-01 05:30:00.000000000 +0530
+++ cvs-1.12.13.1.new/src/passwd.c	2007-03-12 17:04:34.000000000 +0530
@@ -0,0 +1,599 @@
+/*
+ * passwd.c: this file is part of the passwd patch for cvs-1.12.13.
+ * Author: PJP <prasad@ncb.ernet.in>
+ *
+ * Copyright (C) 2006 The Free Software Foundation, Inc.
+ *
+ * Portions Copyright (C) 2006, Prasad J Pandit.
+ *
+ * You may distribute under the terms of the GNU General Public License
+ * as specified in the README file that comes with the CVS source distribution.
+ *
+ * passwd patch for cvs-1.12.13 is ment to add a 'cvs passwd' command to cvs.
+ * This is to facilitate user to change her cvs password from client side using
+ * cvs command line interface.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#   include <config.h>
+#endif
+
+#include "md5.h"
+#include "passwd.h"
+#include "getline.h"
+#include "cvs.h"
+
+#ifdef CVS_ADMIN_GROUP
+#   include <grp.h>
+#endif
+
+# if !HAVE_DECL_FLOCKFILE
+#  undef flockfile
+#  define flockfile(x) ((void) 0)
+# endif
+# if !HAVE_DECL_FUNLOCKFILE
+#  undef funlockfile
+#  define funlockfile(x) ((void) 0)
+# endif
+
+static void init_pass (void);
+static void exit_pass (void);
+static void read_pass (FILE *);
+static void write_pass (FILE *);
+static void insert (const char *);
+static void generate_salt (char *);
+static char *read_new_passwd (void);
+static char *encrypt_pass (const char *);
+static void alias (const char *, const char *);
+static int  gettok (const char *, char, char **);
+static void change_pass (const char *, const char *);
+
+enum op_mode { PASSWD = 0, ADD = 1, DISABLE = 2,
+               DELETE = 4, ALIAS = 8, RALIAS = 16 };
+static enum op_mode mode;
+static bool do_encrypt = false, tokset = false;
+static const char pass_file[] = "/CVSROOT/passwd";
+
+static List *pass_list;         /* password record list */
+static char *rusr, *dpass;      /* remote system user, domain password */
+static char *cmdname;
+static char salt_set[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+                         "abcdefghijklmnopqrstuvwxyz";
+
+
+static const char *const passwd_usage[] =
+{
+    "Usage: %s %s [-a] [-D domain] [-e] [-r real_user] [-R] [-x] [-X]"\
+    " [username]\n",
+    "   -a      add user\n",
+    "   -D      use domain password (Win32 only)\n",
+    "   -e      enable local encrypt\n",
+    "   -r      alias to real system user\n",
+    "   -R      remove alias to real system user\n",
+    "   -x      disable user\n",
+    "   -X      delete user\n",
+    "(Specify the --help global option for a list of other help options)\n",
+    NULL
+};
+
+
+/* check_option: check the command line options */
+static int
+check_option (int argc, char *argv[])
+{
+    int c = 0;
+
+    if (argc < 1)
+        usage (passwd_usage);
+
+    mode = PASSWD;
+    opterr = optind = 0;
+    do_encrypt = tokset = false;
+    while ((c = getopt (argc, argv, "+aD:er:RxX")) != -1)
+    {
+        switch (c)
+        {
+        case 'a':   /* add user */
+            mode |= ADD;
+            break;
+
+        case 'D':   /* use domain password */
+            if (dpass)
+                free (dpass);
+            dpass = xstrdup (optarg);
+            break;
+
+        case 'e':   /* do local encrypt */
+            do_encrypt = true;
+            break;
+
+        case 'r':   /* (remote) real system user */
+            if (rusr)
+                free (rusr);
+            rusr = xstrdup (optarg);
+            mode |= ALIAS;
+            break;
+
+        case 'R':   /* remove alias */
+            mode |= RALIAS;
+            break;
+
+        case 'x':   /* disable user */
+            mode |= DISABLE;
+            break;
+
+        case 'X':   /* delete user */
+            mode |= DELETE;
+            break;
+
+        default:
+            error (0, 0, "invalid option");
+            usage (passwd_usage);
+        }
+    }
+
+    return optind;
+}
+
+
+/*
+ * passwd: This is the `main' function called for both, the cvs-client and the
+ * cvs-server. As a client, it is supposed to read new password from a user
+ * and pass it on to cvs-server. And as a server, to receive username,
+ * password, and other credentials from cvs-client and update the
+ * CVSROOT/passwd file appropriately. It receives the user credentials as
+ * command line arguments in the following format
+ * cvs server passwd [-a] [-D domain] [-e] [-r user] [-R] [-x] [-X]
+ *                   username [current password] [new password]
+ */
+int
+passwd (int argc, char *argv[])
+{
+    Node *tmp = NULL;
+    int i = 0, n = 0, ret = 0;
+    char *key = NULL, *msg = NULL;
+    char *usr = NULL, *curpass = NULL, *newpass = NULL;
+
+    cmdname = argv[0];
+    n = check_option (argc, argv);
+    argc -= n;
+    argv += n;
+
+#ifdef CLIENT_SUPPORT
+    if (current_parsed_root && current_parsed_root->isremote)
+    {                               /* cvs client */
+        usr = (argc > 0) ? argv[0] : current_parsed_root->username;
+
+        start_server ();
+
+        if (!supported_request ("passwd"))
+            error (1, 0, "server does not support `%s'", cmdname);
+        if (!usr && (mode & ADD || mode & DISABLE || mode & DELETE
+                    || mode & ALIAS || mode & RALIAS))
+            error (1, 0, "this option requires argument [username]");
+
+        if (mode & ADD)
+            send_arg ("-a");        /* add user */
+        if (dpass)
+        {
+            option_with_arg ("-D", dpass);
+            free (dpass);
+            dpass = NULL;
+        }
+        if (do_encrypt)
+        {
+            if (!supported_request ("passwd-e"))
+                error (1, 0, "server does not support `-e' option");
+            send_arg ("-e");
+        }
+        if (mode & ALIAS)
+        {
+            option_with_arg ("-r", rusr);   /* make alias */
+            free (rusr);
+            rusr = NULL;
+        }
+        if (mode & RALIAS)
+            send_arg ("-R");        /* remove alias */
+        if (mode & DISABLE)
+            send_arg ("-x");        /* disable user */
+        if (mode & DELETE)
+            send_arg ("-X");        /* delete user */
+        if (!mode)
+        {                           /* change password */
+            printf ("Changing password for `%s'\n", usr);
+            if (supported_request ("passwd-chk-curpass"))
+            {
+                key = getpass ("(current) CVS password: ");
+                if (!key)
+                    error (1, errno, "failed to read password");
+                curpass = scramble (key);
+                free (key);
+                key = NULL;
+            }
+            if (!(newpass = read_new_passwd ()))
+                return -1;
+            if (strlen (newpass) > MAX_LEN)    /* MAX_LEN = 128 */
+                error (0, 0, "warning: password too long");
+            if (do_encrypt)
+                newpass = encrypt_pass (newpass);
+            newpass = scramble (newpass);
+        }
+        if (usr)
+            send_arg (usr);
+        else
+            send_arg ("*");
+        if (curpass)
+            send_arg (curpass);
+        if (newpass)
+            send_arg (newpass);
+        send_to_server ("passwd\012", 0);
+        ret = get_responses_and_close ();
+    }
+#endif
+
+
+#ifdef SERVER_SUPPORT
+    if (server_active)
+    {                               /* cvs server */
+        if (!argc)
+            error (1, 0, "username missing");
+        usr = strcmp(argv[0], "*") ? argv[0] : CVS_Username;
+
+        if ((mode & ADD || mode & ALIAS || mode & RALIAS || mode & DISABLE
+            || mode & DELETE || strcmp (usr, CVS_Username)) && !is_admin ())
+            error (1, 0, "only cvs admin can do that: permission denied!");
+        if (!strcmp (argv[0], CVS_Username)
+            && (mode & DISABLE || mode & DELETE))
+            error (1, 0, "it's a suicide: operation abandoned!");
+
+        init_pass ();
+        if (mode & ADD)
+        {                           /* -a add user */
+            tmp = findnode (pass_list, usr);
+            if (tmp)
+                error (1, 0, "name `%s' is not unique", usr);
+            key = Xasprintf ("%s::\n", usr);
+            insert (key);
+        }
+        if (dpass)
+        {
+            free (dpass);
+            dpass = NULL;
+            error (1, 0, "option `-D domain' is not supported by server");
+        }
+        if (mode & ALIAS)
+        {
+            alias (usr, rusr);      /* -r make alias */
+            free (rusr);
+            rusr = NULL;
+        }
+        if (mode & RALIAS)
+            alias (usr, "");        /* -R remove alias */
+        if (mode & DISABLE)
+            change_pass (usr, "#DISABLED#");  /* -x disable user */
+        if (mode & DELETE)
+        {
+            tmp = findnode (pass_list, usr);
+            if (!tmp)
+                error (1, 0, "user `%s' not found", usr);
+            delnode (tmp);          /* -X delete user */
+        }
+        if (!mode)
+        {                           /* change password */
+            if (argc < 2)
+                error (1, 0, "password missing");
+
+            /*
+             * We needn't check the current password, if an administrator
+             * is trying to (re)set the users password.
+             */
+            if ((argc > 2) && !strcmp (argv[i++], CVS_Username))
+            {
+                curpass = descramble (argv[i]);
+                key = current_parsed_root->directory;
+                if (!check_password (usr, curpass, key))
+                    error (1, 0, "user authentication failed!");
+            }
+            key = descramble (argv[++i]);
+            newpass = (do_encrypt == false) ? encrypt_pass (key) : key;
+            newpass = xstrdup (newpass);
+            change_pass (usr, newpass);
+        }
+        exit_pass ();
+    }
+#endif
+
+    if (curpass) free (curpass);
+    if (newpass) free (newpass);
+    if (current_parsed_root->password)
+    {
+        free (current_parsed_root->password);
+        current_parsed_root->password = NULL;
+    }
+    return ret;
+}
+
+
+/* init_pass: initialize password record list by reading it from file  */
+static void
+init_pass (void)
+{
+    FILE *fpass = NULL;
+    char *fname = NULL;
+
+    pass_list = getlist ();
+    fname = Xasprintf ("%s%s", current_parsed_root->directory, pass_file);
+    if ((fpass = fopen (fname, "r")) == NULL)
+        error (1, errno, "could not open: `%s'", fname);
+    flockfile (fpass); /* acquire exclussive lock on CVSROOT/passwd file */
+    read_pass (fpass);
+    funlockfile (fpass);
+    if (fclose (fpass) != 0)
+        error (1, errno, "could not close: `%s'", fname);
+
+    free (fname);
+}
+
+
+/* exit_pass: write password list to the file and release the list */
+static void
+exit_pass (void)
+{
+    FILE *fpass = NULL;
+    char *fname = NULL;
+
+    fname = Xasprintf ("%s%s", current_parsed_root->directory, pass_file);
+    if ((fpass = fopen (fname, "w")) == NULL)
+        error (1, errno, "could not open: `%s'", fname);
+    flockfile (fpass); /* acquire exclussive lock on CVSROOT/passwd file */
+    write_pass (fpass);
+    funlockfile (fpass);
+    if (fclose (fpass) != 0)
+        error (1, errno, "could not close: `%s'", fname);
+
+    dellist (&pass_list);
+    free (fname);
+}
+
+
+/* encrypt_pass: encrypt the given password using md5 based algorithm */
+static char *
+encrypt_pass (const char *pass)
+{
+    char *ret = NULL, salt[SALTSIZE];
+
+    assert (pass != NULL);
+
+    generate_salt (salt);
+    if (!(ret = crypt (pass, salt)))
+        error (1, errno, "encryption failed");
+
+    return ret;
+}
+
+
+/*
+ * generate_salt: generate an 11 character salt, to be used by crypt(3) for
+ * encryption purpose
+ */
+static void
+generate_salt(char *psalt)
+{
+#define DIV  64
+    int i = 0;
+    time_t tt;
+
+    assert (psalt != NULL);
+
+    tt = time (&tt);
+    srand (tt * getpid ());
+    psalt[i++] = '$';
+    psalt[i++] = '1';
+    psalt[i++] = '$';
+    while (i < SALTSIZE)
+        psalt[i++] = salt_set[(rand () % DIV)];
+    psalt[i - 1] = '\0';
+}
+
+
+/* read_new_passwd: read new password from user    */
+static char *
+read_new_passwd (void)
+{
+#define TRY_CNT    3
+#define MIN_LEN    6
+    short flag = 1, cnt = 0;
+    char *pass = NULL, *cpass = NULL;
+
+    while (flag && (cnt++ < TRY_CNT))
+    {
+        pass = xstrdup (getpass ("New CVS password: "));
+        if (!pass)
+            error (1, errno, "failed to read password");
+        if (strlen (pass) < MIN_LEN)
+        {
+            free (pass);
+            pass = NULL;
+            error (0, 0, "password too short");
+            continue;
+        }
+        cpass = xstrdup (getpass ("Retype new CVS password: "));
+        if (!cpass)
+            error (1, errno, "failed to read password");
+        if (flag = strcmp (pass, cpass))
+        {
+            free (pass);
+            free (cpass);
+            pass = cpass = NULL;
+            error (0, 0, "passwords do not match");
+        }
+    }
+    if (flag && pass)
+    {
+        free (pass);
+        pass = NULL;
+    }
+
+    return pass;
+}
+
+
+/*
+ * change_pass: change the user password in password list created by
+ * read_pass
+ */
+static void
+change_pass (const char *usr, const char *pass)
+{
+    int n = -1;
+    Node *tmp = NULL;
+    char *lusr = NULL, *rec = NULL;
+
+    assert (usr != NULL);
+    assert (pass != NULL);
+
+    tmp = findnode (pass_list, usr);
+    if (!tmp)
+        error (1, 0, "user `%s' not found", usr);
+
+    /*
+     * tmp->data is of the form...
+     * username[:password[:mapped local username]]
+     */
+    n = gettok (tmp->data, ':', &lusr);
+    free (lusr);
+    lusr = NULL;          /* skip username */
+
+    n = (n != 0) ? gettok (tmp->data, ':', &lusr) : 0;
+    free (lusr);
+    lusr = NULL;          /* skip password */
+
+    /* get mapped local username */
+    n = (n != 0) ? gettok (tmp->data, ':', &lusr) : 0;
+    if (lusr != NULL)
+    {
+        rec = Xasprintf ("%s:%s:%s\n", usr, pass, lusr);
+        free (lusr);
+    }
+    else
+        rec = Xasprintf ("%s:%s\n", usr, pass);
+
+    free (tmp->data);
+    tmp->data = rec;
+    tokset = true;
+}
+
+
+/* remove_alias: remove the real system user alias of the given cvs user */
+static void
+alias (const char *usr, const char *als)
+{
+    int n = -1;
+    Node *tmp = NULL;
+    char *pass = NULL, *rec = NULL;
+
+    assert (usr != NULL);
+    assert (als != NULL);
+
+    tmp = findnode (pass_list, usr);
+    if (!tmp)
+        error (1, 0, "user `%s' not found", usr);
+
+    n = gettok (tmp->data, ':', &pass);
+    free (pass);
+    pass = NULL;           /* skip username */
+    n = (n != 0) ? gettok (tmp->data, ':', &pass) : 0;
+    n = (n != 0) ? gettok (tmp->data, ':', &rec) : 0;
+    free (rec);
+    rec = NULL;             /* skip alias */
+    rec = Xasprintf ("%s:%s:%s\n", usr, (pass != NULL) ? pass : "", als);
+    free (tmp->data);
+    tmp->data = rec;
+    tokset = true;
+
+    if (pass) free (pass);
+}
+
+
+/*
+ * gettok: returns a token into 'ret', from given string 's', comprising of
+ * characters up to next occurrence of 'delim' character in 's'. also returns
+ * an integer value greater than zero(0) when more token are available, and
+ * of zero(0) when an end of string 's' is reached.
+ */
+static int
+gettok (const char *s, char delim, char **ret)
+{
+    int j = 0;
+    char buf[BUFLEN];   /* BUFLEN = 512 */
+    static int i = 0;
+
+    if (tokset) i = 0;
+    memset (buf, 0, BUFLEN);
+    *ret = NULL;
+    while ((s[i] != delim) && (s[i] != '\0') && (j < BUFLEN - 1))
+        buf[j++] = s[i++];
+    if (buf[j - 1] == '\n')
+        buf[j - 1] = '\0';
+    buf[j] = '\0';
+    if (buf[0] != '\n')
+        *ret = xstrdup (buf);
+    (s[i] == '\0') ? i = 0 : i++;
+    tokset = false;
+
+    return i;
+}
+
+
+/*
+ * read_pass: reads the CVSROOT/passwd file and build a linked list of
+ * records.
+ */
+static void
+read_pass (FILE *fp)
+{
+    size_t len = 0;
+    char *buf = NULL, *str = NULL;
+
+    assert (fp != NULL);
+
+    while (getline (&buf, &len, fp) > 0)
+    {
+        str = xstrdup (buf);
+        insert (str);
+        free (buf);
+        buf = NULL;
+    }
+}
+
+
+/* write_pass: write all user credentials to CVSROOT/passwd file */
+static void
+write_pass (FILE *fp)
+{
+    Node *i = NULL, *head = pass_list->list;
+
+    assert (fp != NULL);
+
+    for (i = head->next; i != head; i = i->next)
+        fputs (i->data, fp);
+}
+
+
+/* insert: insert new rerord in password list    */
+static void
+insert (const char *str)
+{
+    Node *tmp = NULL;
+
+    assert (str != NULL);
+
+    tmp = getnode ();
+    tmp->type = PASSWDNODE;
+    gettok (str, ':', &tmp->key);
+    tmp->data = (char *) str;
+    tmp->len = strlen (str);
+    addnode (pass_list, tmp);
+    tokset = true;
+}
diff -Naur cvs-1.12.13.1/src/passwd.h cvs-1.12.13.1.new/src/passwd.h
--- cvs-1.12.13.1/src/passwd.h	1970-01-01 05:30:00.000000000 +0530
+++ cvs-1.12.13.1.new/src/passwd.h	2007-03-12 17:04:43.000000000 +0530
@@ -0,0 +1,34 @@
+/*
+ * passwd.h: this file is part of the passwd patch for cvs-1.12.13.
+ * Author: PJP <prasad@ncb.ernet.in>
+ *
+ * Copyright (C) 2006 The Free Software Foundation, Inc.
+ *
+ * Portions Copyright (C) 2006, Prasad J Pandit.
+ *
+ * You may distribute under the terms of the GNU General Public License
+ * as specified in the README file that comes with the CVS source distribution.
+ *
+ * passwd patch for cvs-1.12.13 is ment to add a 'cvs passwd' command to cvs.
+ * This is to facilitate user to change her cvs password from client side using
+ * cvs command line interface.
+ *
+ */
+
+#ifndef PASSWD_H
+#define PASSWD_H
+
+#define BUFLEN     512
+#define MAX_LEN    128
+#define SALTSIZE    12
+
+/*
+ * passwd: is the main function for cvs passwd. called by cvs-client, as well
+ * as cvs-server. When invoked by client, is supposed to read new password
+ * and/or other credentials from user and pass it on to the cvs server. On the
+ * server side, it receives the password and/or other credentials sent by the
+ * client, and updates the CVSROOT/passwd file appropriately
+ */
+int passwd (int, char *[]);
+
+#endif
diff -Naur cvs-1.12.13.1/src/sanity.sh cvs-1.12.13.1.new/src/sanity.sh
--- cvs-1.12.13.1/src/sanity.sh	2006-09-14 21:03:41.000000000 +0530
+++ cvs-1.12.13.1.new/src/sanity.sh	2007-03-08 16:13:57.000000000 +0530
@@ -2125,6 +2125,7 @@
 	tests="${tests} writeproxy writeproxy-noredirect writeproxy-ssh"
 	tests="${tests} writeproxy-ssh-noredirect"
 	tests="$tests openpgp"
+	tests="${tests} passwd"
 else
 	tests="$*"
 fi
@@ -31832,6 +31833,345 @@
 	  ;;
 
 
+	# PJP <prasad@ncb.ernet.in>
+	# passwd is a remote test, you need to set the ${PWCVSROOT} environment 
+	# variable to valid cvsroot like ":pserver:user@host:2401/path/to/cvsroot"
+	# and also make sure that the remote cvs server supports the passwd 
+	# command (or request).
+	passwd)	# check cvs passwd command
+		if $remote; then
+            if [ -n "$remotehost" ]; then
+                continue;
+            fi
+            username=`$ID -un`
+            tmpusr="cvs"
+            save_servercvs=$servercvs
+            servercvs=$testcvs
+            cd $testdir
+            touch /tmp/cvs-sanity/home/.cvspass
+            mkdir 1; cd 1;
+            cat >$CVSROOT_DIRNAME/CVSROOT/passwd <<EOF
+testme:q6WV9d2t848B2:$username
+dontroot:q6WV9d2t848B2:root
+anonymous::$username
+$username:
+willfail:   :whocares
+EOF
+
+            # Test how the passwd command works when no arguments are given
+            dotest passwd-server-1 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver " \
+"${DOTSTAR}I LOVE YOU
+E cvs \[passwd aborted\]: username missing
+error  " << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+passwd
+EOF
+
+            # Test when only username is given and password is not
+            dotest passwd-server-2 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+E cvs \[passwd aborted\]: password missing
+error  " << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument testme
+passwd 
+EOF
+
+            # Test when username & password is given
+            dotest passwd-server-3 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+ok" << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument testme
+Argument Ay::''d
+passwd 
+EOF
+
+            # Test when username, current passwrod, & new password
+            # is given
+            dotest passwd-server-4 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+ok" << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::''d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument testme
+Argument Ay::''d
+Argument Ay::'d
+passwd 
+EOF
+
+            # Test when username, current passwrod, & new password
+            # is given, but current password is wrong
+            dotest passwd-server-5 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+E cvs \[passwd aborted\]: user authentication failed!
+error  " << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument testme
+Argument Ay::''d
+Argument Ay::'d
+passwd 
+EOF
+
+            # Test an invalid option
+            dotest passwd-server-6 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+E cvs passwd: invalid option
+E Usage: cvs passwd \[-a\] \[-D domain\] \[-e\] \[-r real_user\] \[-R\] \[-x\] \[-X\] \[username\]
+E    -a      add user
+E    -D      use domain password (Win32 only)
+E    -e      enable local encrypt
+E    -r      alias to real system user
+E    -R      remove alias to real system user
+E    -x      disable user
+E    -X      delete user
+E (Specify the --help global option for a list of other help options)
+error  " << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -v
+passwd
+EOF
+
+            # Test when '-D domain' option is used
+            dotest passwd-server-7 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+E cvs \[passwd aborted\]: option \`-D domain' is not supported by server
+error  " << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -D
+Argument helloworld
+Argument testme
+Argument Ay::''d
+passwd 
+EOF
+
+            # Test option -a
+            dotest passwd-server-8 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+ok" << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -a
+Argument $tmpusr
+passwd 
+EOF
+
+            # Test option -r without real_user
+            dotest passwd-server-9 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+E cvs passwd: invalid option
+E Usage: cvs passwd \[-a\] \[-D domain\] \[-e\] \[-r real_user\] \[-R\] \[-x\] \[-X\] \[username\]
+E    -a      add user
+E    -D      use domain password (Win32 only)
+E    -e      enable local encrypt
+E    -r      alias to real system user
+E    -R      remove alias to real system user
+E    -x      disable user
+E    -X      delete user
+E (Specify the --help global option for a list of other help options)
+error  " << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -r
+passwd 
+EOF
+
+            # Test option -r real_user
+            dotest passwd-server-10 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+ok" << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -r
+Argument $username
+Argument $tmpusr
+passwd 
+EOF
+
+            # Test option -R 
+            dotest passwd-server-11 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+ok" << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -R
+Argument $tmpusr
+passwd 
+EOF
+
+            # Test option -x 
+            dotest passwd-server-12 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+ok" << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -x
+Argument $tmpusr
+passwd 
+EOF
+
+            # Test option -X 
+            dotest passwd-server-13 \
+"$servercvs --allow-root=${CVSROOT_DIRNAME} pserver" \
+"${DOTSTAR}I LOVE YOU
+ok" << EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+Argument -X
+Argument $tmpusr
+passwd 
+EOF
+
+            CVSROOT_save=$CVSROOT
+            CVSROOT=$PWCVSROOT
+            if [ -z "$PWCVSROOT" ]; then
+                echo -n "\$PWCVSOOT not set: skipping test:";
+                echo " passwd-in, passwd-[14-23], & passwd-out";
+                echo "see TESTS";
+                continue;
+            fi    
+
+            # First thing fitst `cvs login`
+            echo "Logging in user: $username"
+            dotest passwd-in "$testcvs -d $CVSROOT login "\
+            "Logging in to $CVSROOT" 
+
+            # Test an invalid option/switch
+            dotest_fail passwd-14 "$testcvs -d $CVSROOT passwd -v" \
+"cvs passwd: invalid option
+Usage: cvs passwd \[-a\] \[-D domain\] \[-e\] \[-r real_user\] \[-R\] \[-x\] \[-X\] \[username\]
+   -a      add user
+   -D      use domain password (Win32 only)
+   -e      enable local encrypt
+   -r      alias to real system user
+   -R      remove alias to real system user
+   -x      disable user
+   -X      delete user
+(Specify the --help global option for a list of other help options)"
+
+            # Test '-D domain' password option
+            echo "Check the '-D domain' option"
+            dotest_fail passwd-15 "$testcvs -d $CVSROOT passwd -D helloworld" \
+            "Changing password for $username
+cvs \[passwd aborted\]: option \`-D domain' is not supported by server"
+
+            # Add new user `cvs passwd -a <username>`
+            echo "Adding user $tmpusr"
+            dotest passwd-16 "$testcvs -d $CVSROOT passwd -a $tmpusr" ""
+
+            # Try adding same(above) user again
+            dotest_fail passwd-17 "$testcvs -d $CVSROOT passwd -a $tmpusr" \
+            "cvs \[passwd aborted\]: name \`$tmpusr' is not unique"
+
+            # Alias the cvs user to real system user `cvs passwd -r <real_user>`
+            echo "Adding alias for user $tmpusr"
+            dotest passwd-18 \
+            "$testcvs -d $CVSROOT passwd -r $username $tmpusr" ""
+
+            # Change password of the user `cvs passwd <username>`
+            echo "Changing password for $tmpusr"
+            dotest passwd-19 "$testcvs -d $CVSROOT passwd $tmpusr" \
+            "Changing password for $tmpusr"
+
+            # Remove alias of a cvs user `cvs passwd -R <username>`
+            echo "Removing alias for user $tmpusr"
+            dotest passwd-20 "$testcvs -d $CVSROOT passwd -R $tmpusr" ""
+
+            # Disable cvs user `cvs passwd -x <username>`
+            echo "Disabling user $tmpusr"
+            dotest passwd-21 "$testcvs -d $CVSROOT passwd -x $tmpusr" ""
+
+            # Delete cvs user `cvs passwd -X <username>`
+            echo "Deleting user $tmpusr"
+            dotest passwd-22 "$testcvs -d $CVSROOT passwd -X $tmpusr" ""
+
+            # Change the self password `cvs passwd`
+            echo "Changing password for $username"
+            dotest passwd-23 "$testcvs -d $CVSROOT passwd " \
+            "Changing password for $username"
+            
+            # Sya goodbye `cvs logout`
+            echo "Logging out $username"
+            dotest passwd-out "$testcvs -d $CVSROOT logout" \
+            "Logging out of $CVSROOT"
+
+            CVSROOT=${CVSROOT_save}; export CVSROOT
+			cd ..; 
+            rm -rf 1;
+            cd ..;
+		fi
+		;;
+
 
 	server)
 	  # Some tests of the server (independent of the client).
@@ -31853,6 +32193,27 @@
 Set MYENV=env-value
 init ${TESTDIR}/crerepos
 EOF
+
+#	server)
+	  # Some tests of the server (independent of the client).
+#	  if $remote; then
+#	    save_servercvs=$servercvs
+#	    servercvs=$testcvs
+#	    dotest server-1 "${servercvs} server" \
+#"E Protocol error: Root request missing
+#error  " <<EOF
+#Directory bogus
+#mumble/bar
+#update
+#EOF
+
+	    # Could also test for relative pathnames here (so that crerepos-6a
+	    # and crerepos-6b can use :fork:).
+	    dotest server-2 "${servercvs} server" "ok" <<EOF
+Set OTHER=variable
+Set MYENV=env-value
+init ${TESTDIR}/crerepos
+EOF
 	    dotest server-3 "test -d ${TESTDIR}/crerepos/CVSROOT" ""
 
 	    # Now some tests of gzip-file-contents (used by jCVS).
@@ -33038,7 +33399,7 @@
 	  save_CVS_SERVER=$CVS_SERVER
 	  ln -s $PRIMARY_CVSROOT_DIRNAME $TESTDIR/primary_link
 	  dotest writeproxy-0 "$CVS_SERVER server" \
-"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version
+"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version passwd passwd-e passwd-chk-curpass
 ok
 ok
 ok" \
@@ -33325,7 +33686,7 @@
 	  mv $TESTDIR/save-root $PRIMARY_CVSROOT_DIRNAME
 
 	  dotest writeproxy-noredirect-5 "$CVS_SERVER server" \
-"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version
+"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version passwd passwd-e passwd-chk-curpass
 ok
 ok
 ok
@@ -33357,7 +33718,7 @@
 	  cd firstdir
 	  echo now you see me >file1
 	  dotest writeproxy-noredirect-6 "$CVS_SERVER server" \
-"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version
+"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version passwd passwd-e passwd-chk-curpass
 ok
 ok
 ok
@@ -33387,7 +33748,7 @@
 	  echo /file1/0/dummy+timestamp// >>CVS/Entries
 
 	  dotest writeproxy-noredirect-7 "$CVS_SERVER server" \
-"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version
+"Valid-requests Root Valid-responses valid-requests Command-prep Referrer Repository Directory Relative-directory Max-dotdot Static-directory Sticky Entry Kopt Checkin-time Modified Signature Base-diff Is-modified Empty-conflicts UseUnchanged Unchanged Notify Hostname LocalDir Questionable Argument Argumentx Global_option Gzip-stream wrapper-sendme-rcsOptions Set ${DOTSTAR}expand-modules ci co update diff log rlog list rlist global-list-quiet ls add remove update-patches gzip-file-contents sign status rdiff tag rtag import admin export history release watch-on watch-off watch-add watch-remove watchers editors edit init annotate rannotate noop version passwd passwd-e passwd-chk-curpass
 ok
 ok
 Mode u=rw,g=rw,o=r
diff -Naur cvs-1.12.13.1/src/server.c cvs-1.12.13.1.new/src/server.c
--- cvs-1.12.13.1/src/server.c	2006-09-15 18:01:56.000000000 +0530
+++ cvs-1.12.13.1.new/src/server.c	2007-03-06 13:02:28.000000000 +0530
@@ -35,6 +35,7 @@
 #include "fileattr.h"
 #include "gpg.h"
 #include "ignore.h"
+#include "passwd.h"
 #include "repos.h"
 #include "watch.h"
 #include "wrapper.h"
@@ -4899,6 +4900,12 @@
 }
 
 
+static void
+serve_passwd (char *arg)
+{
+    do_cvs_command ("passwd", passwd);
+}
+
 
 static void
 serve_init (char *arg)
@@ -6103,6 +6110,9 @@
   REQ_LINE("rannotate", serve_rannotate, 0),
   REQ_LINE("noop", serve_noop, RQ_ROOTLESS),
   REQ_LINE("version", serve_version, RQ_ROOTLESS),
+  REQ_LINE("passwd", serve_passwd, 0),
+  REQ_LINE("passwd-e", serve_noop, RQ_ROOTLESS),
+  REQ_LINE("passwd-chk-curpass", serve_noop, RQ_ROOTLESS),
   REQ_LINE(NULL, NULL, 0)
 
 #undef REQ_LINE
@@ -7174,7 +7184,7 @@
 
 
 /* Return a hosting username if password matches, else NULL. */
-static char *
+char *
 check_password (char *username, char *password, char *repository)
 {
     int rc;
diff -Naur cvs-1.12.13.1/src/server.h cvs-1.12.13.1.new/src/server.h
--- cvs-1.12.13.1/src/server.h	2006-06-12 20:03:02.000000000 +0530
+++ cvs-1.12.13.1.new/src/server.h	2007-03-06 13:06:22.000000000 +0530
@@ -62,6 +62,9 @@
 
 /* pserver user authentication.  */
 # if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
+/* Return a hosting username if password matches, else NULL. */
+char * check_password (char *, char *, char *);
+
 void pserver_authenticate_connection (void);
 # endif
 
diff -Naur cvs-1.12.13.1/TESTS cvs-1.12.13.1.new/TESTS
--- cvs-1.12.13.1/TESTS	2005-09-13 23:42:20.000000000 +0530
+++ cvs-1.12.13.1.new/TESTS	2006-09-26 12:05:32.000000000 +0530
@@ -215,6 +215,8 @@
 
    * $testdir   = the directory this test is taking place in
                   (CVSROOT=$testdir/cvsroot or CVSROOT=:fork:$testdir/cvsroot)
+   * $PWCVSROOT = remote cvsroot, used by passwd test. it is of the form 
+                  ":pserver:user@host:/path/to/cvsroot"
    * $testcvs   = full path to the cvs executable we are testing
    * $PLUS      = expr dependant uninterpreted '+' since this can vary
    * $DOTSTAR   = expr dependant _interpreted_ .* since some exprs don't match
