diff -ur fcrackzip-1.0/Makefile.am fcrackzip-1.0-yalla/Makefile.am
--- fcrackzip-1.0/Makefile.am	2003-02-09 09:15:00.000000000 +0000
+++ fcrackzip-1.0-yalla/Makefile.am	2009-05-04 23:26:30.000000000 +0100
@@ -12,6 +12,7 @@
 noinst_HEADERS = getopt.h
 fcrackzip_SOURCES = main.c crack.c crack.h crc32.h
 fcrackzip_LDADD = @LIBOBJS@
+fcrackzip_LDFLAGS = -lm
 zipinfo_SOURCES = zipinfo.c
 zipinfo_LDADD = @LIBOBJS@
 
diff -ur fcrackzip-1.0/crack.c fcrackzip-1.0-yalla/crack.c
--- fcrackzip-1.0/crack.c	2004-12-27 22:34:49.000000000 +0000
+++ fcrackzip-1.0-yalla/crack.c	2009-05-04 23:15:18.000000000 +0100
@@ -5,11 +5,17 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <math.h>
 #include "crack.h"
 
 u8 pw[MAX_PW + 1] = "aaaaaa";
 u8 *pw_end;			/* must point to the trailing zero byte.  */
 
+extern u8 pw_do_break = 0;
+u8 pw_break[MAX_PW + 1] = "ZZZZZZ";
+u8 charset_[1024];
+unsigned long stop_ch = 0;
+
 u8 files[MAX_FILES * HEADER_SIZE];
 const char *file_path[MAX_FILES];
 int file_count;
@@ -157,5 +163,34 @@
   fclose (f);
 }
 
+
+unsigned long gen_char_check( char *s )
+{
+	int clen = strlen( charset_ );
+	int len = strlen( s );
+	int plen = len;
+	int ix;
+	int iy;
+	unsigned long calc = 0;
+
+	for( ix=0; ix<len; ix++ )
+	{
+		for( iy = 0; iy<clen; iy++ )
+		{
+			if ( charset_[iy] == s[ix] )
+				break;
+		}
+
+		// char in string not in charset
+		if ( clen == iy )
+			return -1;
+		
+		plen--;
+		calc += ( (iy + 1) * pow( clen, plen ) );
+	}
+
+	return calc;
+}
+
 #include "cpmask.c"
 #include "crackdef.c"
diff -ur fcrackzip-1.0/crack.h fcrackzip-1.0-yalla/crack.h
--- fcrackzip-1.0/crack.h	2000-06-19 00:19:07.000000000 +0100
+++ fcrackzip-1.0-yalla/crack.h	2009-05-04 23:15:10.000000000 +0100
@@ -7,6 +7,12 @@
 extern u8 pw[MAX_PW+1];
 extern u8 *pw_end;
 
+extern u8 pw_do_break;
+extern u8 pw_break[MAX_PW+1];
+extern u8 charset_[1024];
+extern unsigned long stop_ch;
+unsigned long gen_char_check( char *s );
+
 /* a gen_func must modify the global variables "pw" and "pw_end" to the next
  * password to be checked and return the number of characters that have
  * changed, counting from the end, or zero, to indicate end of cracking.
diff -ur fcrackzip-1.0/main.c fcrackzip-1.0-yalla/main.c
--- fcrackzip-1.0/main.c	2005-09-10 20:58:44.000000000 +0100
+++ fcrackzip-1.0-yalla/main.c	2009-05-04 23:18:09.000000000 +0100
@@ -220,6 +220,8 @@
   memset (bf_next, bf_last, sizeof bf_next);
   memset (map, 0, 256);
 
+  strcpy( charset_, chars );
+
   for (; *p; p++)
     if (!map[*p])
       {
@@ -230,6 +232,9 @@
 
   bf_next[bf_last] = chars[0];
 
+  if ( pw_do_break )
+      	stop_ch = gen_char_check( pw_break );
+
 /*  { int i; for (i = 0; i < 255; i++) printf ("bf_next [%3d] = %3d\n", i, bf_next[i]);}; */
 }
 
@@ -318,6 +323,7 @@
           "          [-V|--validate]               sanity-check the algortihm\n"
           "          [-v|--verbose]                be more verbose\n"
           "          [-p|--init-password string]   use string as initial password/file\n"
+          "          [-P|--last-password string]   use string as final password to check\n"
           "          [-l|--length min-max]         check password with length min to max\n"
           "          [-u|--use-unzip]              use unzip to weed out wrong passwords\n"
           "          [-m|--method num]             use method number \"num\" (see below)\n"
@@ -348,6 +354,7 @@
   {"validate", no_argument, 0, 'V'},
   {"verbose", no_argument, 0, 'v'},
   {"init-password", required_argument, 0, 'p'},
+  {"last-password", required_argument, 0, 'P'},
   {"length", required_argument, 0, 'l'},
   {"use-unzip", no_argument, 0, 'u'},
   {"method", required_argument, 0, 'm'},
@@ -363,7 +370,7 @@
   char *charset = "aA1!";
   enum { m_benchmark, m_brute_force, m_dictionary } mode = m_brute_force;
 
-  while ((c = getopt_long (argc, argv, "DbBc:hVvp:l:um:2:", options, &option_index)) != -1)
+  while ((c = getopt_long (argc, argv, "DbBc:hVvp:l:um:2:P:", options, &option_index)) != -1)
     switch (c)
       {
       case 'b':
@@ -378,6 +385,11 @@
         strcpy (pw, optarg);
         break;
 
+      case 'P':
+        strcpy( pw_break, optarg );
+	pw_do_break = 1;
+        break;
+
       case 'l':
         pw[0] = 0;
         switch (sscanf (optarg, "%d-%d", &min_length, &max_length))
@@ -548,3 +560,4 @@
 
   return 0;
 }
+
diff -ur fcrackzip-1.0/zipcrack.c fcrackzip-1.0-yalla/zipcrack.c
--- fcrackzip-1.0/zipcrack.c	2003-02-09 09:05:08.000000000 +0000
+++ fcrackzip-1.0-yalla/zipcrack.c	2009-05-04 23:31:03.000000000 +0100
@@ -67,7 +67,17 @@
       sp -= changed * 3;
       p = (u8 *)pw_end - changed;
       
-      if (++crack_count >= 1000000 && verbosity)
+      if ( 0 != stop_ch && crack_count == 1000000 )
+        {
+	  if ( gen_char_check( pw ) > stop_ch )
+	  {
+		  printf( "Stopping at; %s, requested; %s \n", pw, pw_break );
+		  return 0;
+	  }
+        }
+
+
+      if (++crack_count > 1000000 && verbosity)
         {
           printf ("checking pw %-40.40s\r", pw), fflush (stdout);
           crack_count = 0;

