Many files:
  pass*.c, super.c: Massive changes to avoid using printf and com_err
  	routines.  All diagnostic messages are now routed through the
  	fix_problem interface.
  pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
  problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
  	PR_2_DUP_DOT_DOT.
  problem.c: Added new problem codes for some of the superblock
  	corruption checks, and for the pass header messages.  ("Pass
  	1: xxxxx")
  util.c (print_resource_track): Now takes a description argument.
  super.c, unix.c, e2fsck.c: New files to separate out the
  	operating-specific operations out from e2fsck.c.  e2fsck.c now
  	contains the global e2fsck context management routines, and
  	super.c contains the "pass 0" initial validation of the
  	superblock and global block group descriptors.
  pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
  	(nearly) all global variables and moved them to the e2fsck
  	context structure.
  problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
  	PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
  	PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
  Updated tests to align with e2fsck problem.c changes.

diff --git a/e2fsck/message.c b/e2fsck/message.c
index b9f9dea..673c463 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -15,8 +15,11 @@
  *
  * 	%b	<blk>			block number
  * 	%B	<blkcount>		integer
+ * 	%c	<blk2>			block number
  * 	%di	<dirent>->ino		inode number
  * 	%dn	<dirent>->name		string
+ * 	%dr	<dirent>->rec_len
+ * 	%dl	<dirent>->name_len
  * 	%D	<dir> 			inode number
  * 	%g	<group>			integer
  * 	%i	<ino>			inode number
@@ -29,6 +32,7 @@
  * 	%If	<inode> -> i_file_acl
  * 	%Id	<inode> -> i_dir_acl
  * 	%j	<ino2>			inode number
+ * 	%m	<com_err error message>
  * 	%N	<num>
  *	%p	ext2fs_get_pathname of directory <ino>
  * 	%P	ext2fs_get_pathname of <dirent>->ino with <ino2> as
@@ -37,6 +41,8 @@
  * 	%q	ext2fs_get_pathname of directory <dir>
  * 	%Q	ext2fs_get_pathname of directory <ino> with <dir> as
  * 			the containing directory.
+ * 	%s	<str>			miscellaneous string
+ * 	%S	backup superblock
  *
  * The following '@' expansions are supported:
  *
@@ -49,12 +55,15 @@
  * 	@d	directory
  * 	@e	entry
  * 	@E	Entry '%Dn' in %p (%i)
+ * 	@f	filesystem
  * 	@F	for @i %i (%Q) is
  * 	@g	group
  * 	@l	lost+found
  * 	@L	is a link
  * 	@u	unattached
  * 	@r	root inode
+ * 	@s	should be 
+ * 	@S	superblock
  * 	@z	zero-length
  */
 
@@ -90,6 +99,7 @@
 	"ddirectory",
 	"eentry",
 	"E@e '%Dn' in %p (%i)",
+	"ffilesystem",
 	"Ffor @i %i (%Q) is",
 	"ggroup",
 	"llost+found",
@@ -97,6 +107,7 @@
 	"uunattached",
 	"rroot @i",
 	"sshould be",
+	"Ssuper@b",
 	"zzero-length",
 	"@@",
 	0
@@ -145,8 +156,8 @@
  * expansion; an @ expression can contain further '@' and '%'
  * expressions. 
  */
-static _INLINE_ void expand_at_expression(ext2_filsys fs, char ch,
-					  struct problem_context *ctx,
+static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
+					  struct problem_context *pctx,
 					  int *first)
 {
 	const char **cpp, *str;
@@ -162,7 +173,7 @@
 			*first = 0;
 			fputc(toupper(*str++), stdout);
 		}
-		print_e2fsck_message(fs, str, ctx, *first);
+		print_e2fsck_message(ctx, str, pctx, *first);
 	} else
 		printf("@%c", ch);
 }
@@ -242,6 +253,12 @@
 			len = dirent->rec_len;
 		printf("%.*s", dirent->name_len, dirent->name);
 		break;
+	case 'r':
+		printf("%u", dirent->rec_len);
+		break;
+	case 'l':
+		printf("%u", dirent->name_len);
+		break;
 	default:
 	no_dirent:
 		printf("%%D%c", ch);
@@ -265,6 +282,9 @@
 	case 'B':
 		printf("%d", ctx->blkcount);
 		break;
+	case 'c':
+		printf("%u", ctx->blk2);
+		break;
 	case 'd':
 		printf("%lu", ctx->dir);
 		break;
@@ -277,6 +297,9 @@
 	case 'j':
 		printf("%lu", ctx->ino2);
 		break;
+	case 'm':
+		printf("%s", error_message(ctx->errcode));
+		break;
 	case 'N':
 		printf("%u", ctx->num);
 		break;
@@ -293,6 +316,12 @@
 	case 'Q':
 		print_pathname(fs, ctx->dir, ctx->ino);
 		break;
+	case 'S':
+		printf("%d", get_backup_sb(fs));
+		break;
+	case 's':
+		printf("%s", ctx->str);
+		break;
 	default:
 	no_context:
 		printf("%%%c", ch);
@@ -300,25 +329,26 @@
 	}
 }	
 
-void print_e2fsck_message(ext2_filsys fs, const char *msg,
-			  struct problem_context *ctx, int first)
+void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+			  struct problem_context *pctx, int first)
 {
+	ext2_filsys fs = ctx->fs;
 	const char *	cp;
 	int		i;
 	
 	for (cp = msg; *cp; cp++) {
 		if (cp[0] == '@') {
 			cp++;
-			expand_at_expression(fs, *cp, ctx, &first);
+			expand_at_expression(ctx, *cp, pctx, &first);
 		} else if (cp[0] == '%' && cp[1] == 'I') {
 			cp += 2;
-			expand_inode_expression(*cp, ctx);
+			expand_inode_expression(*cp, pctx);
 		} else if (cp[0] == '%' && cp[1] == 'D') {
 			cp += 2;
-			expand_dirent_expression(*cp, ctx);
+			expand_dirent_expression(*cp, pctx);
 		} else if ((cp[0] == '%')) {
 			cp++;
-			expand_percent_expression(fs, *cp, ctx);
+			expand_percent_expression(fs, *cp, pctx);
 		} else {
 			for (i=0; cp[i]; i++)
 				if ((cp[i] == '@') || cp[i] == '%')