diff -urNp pam_passwdqc-1.0.5-orig/pam_passwdqc.c pam_passwdqc-1.0.5/pam_passwdqc.c
--- pam_passwdqc-1.0.5-orig/pam_passwdqc.c	2008-02-12 15:11:13.000000000 -0500
+++ pam_passwdqc-1.0.5/pam_passwdqc.c	2009-09-28 12:10:32.171696694 -0400
@@ -70,6 +70,8 @@ typedef struct {
 	passwdqc_params_t qc;
 	int flags;
 	int retry;
+	char oldpass_prompt_file[FILE_LEN+1];
+	char newpass_prompt_file[FILE_LEN+1];
 } params_t;
 
 static params_t defaults = {
@@ -79,10 +81,13 @@ static params_t defaults = {
 		3,				/* passphrase_words */
 		4,				/* match_length */
 		1,				/* similar_deny */
-		42				/* random_bits */
+		42,				/* random_bits */
+		1				/* firstupper_lastdigit_check */
 	},
 	F_ENFORCE_EVERYONE,			/* flags */
-	3					/* retry */
+	3,					/* retry */
+	"",					/* oldpass_prompt_file */
+	""					/* newpass_prompt_file */
 };
 
 #define PROMPT_OLDPASS \
@@ -361,6 +366,37 @@ static int parse(params_t *params, pam_h
 		if (!strcmp(*argv, "use_authtok")) {
 			params->flags |= F_USE_AUTHTOK;
 		} else
+		if (!strcmp(*argv, "disable_firstupper_lastdigit_check")) {
+			params->qc.firstupper_lastdigit_check = 0;
+		} else
+		if (!strncmp(*argv, "oldpass_prompt_file=", 20)) {
+			int n;
+			FILE *fp = fopen(*argv + 20, "r");
+			if (fp) {
+				n=fread(params->oldpass_prompt_file, sizeof(char), FILE_LEN, fp);
+				if (0==n || ferror(fp)!=0 ) {
+					memset(params->oldpass_prompt_file, '\0', FILE_LEN+1);
+				}
+				else {
+					feof(fp)? (params->oldpass_prompt_file[n-1]='\0'): (params->oldpass_prompt_file[n]='\0');
+				}
+				fclose(fp);
+			}
+		} else
+		if (!strncmp(*argv, "newpass_prompt_file=", 20)) {
+			int n;
+			FILE *fp = fopen(*argv + 20, "r");
+			if (fp) {
+				n=fread(params->newpass_prompt_file, sizeof(char), FILE_LEN, fp);
+				if (0==n || ferror(fp)!=0 ) {
+					memset(params->newpass_prompt_file, '\0', FILE_LEN+1);
+				}
+				else {
+                                        feof(fp)? (params->newpass_prompt_file[n-1]='\0'): (params->newpass_prompt_file[n]='\0');
+				}
+				fclose(fp);
+			}
+		} else
 			break;
 		argc--; argv++;
 	}
@@ -406,7 +442,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand
 
 	if (ask_oldauthtok && !am_root(pamh)) {
 		status = converse(pamh, PAM_PROMPT_ECHO_OFF,
-		    PROMPT_OLDPASS, &resp);
+		    strlen(params.oldpass_prompt_file) ? params.oldpass_prompt_file : PROMPT_OLDPASS, &resp);
 
 		if (status == PAM_SUCCESS) {
 			if (resp && resp->resp) {
@@ -540,8 +576,7 @@ retry:
 		    MESSAGE_RANDOMFAILED : MESSAGE_MISCONFIGURED);
 		return PAM_AUTHTOK_ERR;
 	}
-
-	status = converse(pamh, PAM_PROMPT_ECHO_OFF, PROMPT_NEWPASS1, &resp);
+	status = converse(pamh, PAM_PROMPT_ECHO_OFF, strlen(params.newpass_prompt_file) ? params.newpass_prompt_file : PROMPT_NEWPASS1, &resp);
 	if (status == PAM_SUCCESS && (!resp || !resp->resp))
 		status = PAM_AUTHTOK_ERR;
 
diff -urNp pam_passwdqc-1.0.5-orig/passwdqc_check.c pam_passwdqc-1.0.5/passwdqc_check.c
--- pam_passwdqc-1.0.5-orig/passwdqc_check.c	2008-02-12 14:31:52.000000000 -0500
+++ pam_passwdqc-1.0.5/passwdqc_check.c	2009-09-25 22:45:16.080842425 -0400
@@ -90,10 +90,12 @@ static int is_simple(passwdqc_params_t *
 
 /* Upper case characters and digits used in common ways don't increase the
  * strength of a password */
-	c = (unsigned char)newpass[0];
-	if (uppers && isascii(c) && isupper(c)) uppers--;
-	c = (unsigned char)newpass[length - 1];
-	if (digits && isascii(c) && isdigit(c)) digits--;
+	if (params->firstupper_lastdigit_check) {
+		c = (unsigned char)newpass[0];
+		if (uppers && isascii(c) && isupper(c)) uppers--;
+		c = (unsigned char)newpass[length - 1];
+		if (digits && isascii(c) && isdigit(c)) digits--;
+	}
 
 /* Count the number of different character classes we've seen.  We assume
  * that there are no non-ASCII characters for digits. */
diff -urNp pam_passwdqc-1.0.5-orig/passwdqc.h pam_passwdqc-1.0.5/passwdqc.h
--- pam_passwdqc-1.0.5-orig/passwdqc.h	2008-02-12 14:30:00.000000000 -0500
+++ pam_passwdqc-1.0.5/passwdqc.h	2009-09-25 14:08:56.214695858 -0400
@@ -7,12 +7,15 @@
 
 #include <pwd.h>
 
+#define FILE_LEN		4096	/* Max file len = 4096 */
+
 typedef struct {
 	int min[5], max;
 	int passphrase_words;
 	int match_length;
 	int similar_deny;
 	int random_bits;
+	int firstupper_lastdigit_check;
 } passwdqc_params_t;
 
 extern char _passwdqc_wordset_4k[0x1000][6];
diff -urNp pam_passwdqc-1.0.5-orig/README pam_passwdqc-1.0.5/README
--- pam_passwdqc-1.0.5-orig/README	2008-02-12 14:43:33.000000000 -0500
+++ pam_passwdqc-1.0.5/README	2009-09-28 12:12:40.251016423 -0400
@@ -41,9 +41,12 @@ words (see the "passphrase" option below
 N3 and N4 are used for passwords consisting of characters from three
 and four character classes, respectively.
 
+	disable_firstupper_lastdigit_check	[]
+
 When calculating the number of character classes, upper-case letters
 used as the first character and digits used as the last character of a
-password are not counted.
+password are not counted. To disable this, you can specify 
+"disable_firstupper_lastdigit_check".
 
 In addition to being sufficiently long, passwords are required to
 contain enough different characters for the character classes and
@@ -142,6 +145,14 @@ This disables user interaction within pa
 the only difference between "use_first_pass" and "use_authtok" is that
 the former is incompatible with "ask_oldauthtok".
 
+	oldpass_prompt_file=absolute-file-path	[]
+	newpass_prompt_file=abosulte-file-path	[]
+
+The options "oldpass_prompt_file" and "newpass_prompt_file" can be used
+to override prompts while requesting old password and new password, 
+respectively. The maximum size of the prompt files can be 4096 
+characters at present. If the file size is more than 4096 characters, the
+output will be truncated to 4096 characters.
 -- 
 Solar Designer <solar at openwall.com>
 
