diff --git a/Makefile b/Makefile
index 6c7a74a..5008847 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ SHELL = /bin/sh
 # also change the version over in build.com
 #
 
-CURRVER = 4.4.3
+CURRVER = 4.4.3hb
 
 ##########
 HAVE_REMOTE =
@@ -68,8 +68,11 @@ CFLAGS = $(LONGOPT)
 .1.txt: ; groff -man -Tascii $*.1 > $*.txt
 
 .1.ps: ;  groff -man -Tps $*.1 > $*.ps
-
+ifneq ($(SHELL which ps2pdf),"")
+.1.pdf: ; ps2pdf $*.ps $*.pdf
+else
 .1.pdf: ; pstopdf $*.ps -o $*.pdf
+endif
 
 SRCS = vmsbackup.c match.c getoptmain.c
 OBJS = ${SRCS:.c=.o}
@@ -79,10 +82,12 @@ DOCS = vmsbackup.txt vmsbackup.ps  vmsbackup.pdf
 #
 # Build it all
 #
-all : vbver  vmsbackup  vmsbackup.info
+all : vmsbackup  vmsbackup.info
+
+vmsbackupver.h :
+	echo "#define VMSBACKUPVERSION \"$(CURRVER)\"" > $@
 
-vbver : 
-	echo "#define VMSBACKUPVERSION \"$(CURRVER)\"" > vmsbackupver.h
+getoptmain.o: getoptmain.c vmsbackupver.h
 
 vmsbackup : $(OBJS)
 
@@ -103,7 +108,7 @@ install :
 #
 .PHONY : clean
 clean :
-	rm -f vmsbackup *.o core
+	rm -f vmsbackup vmsbackupver.h *.o core
 	rm -f vmsbackup.txt vmsbackup.ps vmsbackup.pdf
 	rm -f vmsbackup-src_*.tar
 
diff --git a/NEWS b/NEWS
index b45bec8..9fa0b47 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,60 @@
+Changes in 4.4.3hb
+  7-Oct-2016
+
+* Fix writing VAR/VFC records
+  In case the record length was the last word in a buffer, the fixed
+  control field wasn't correctly handled: it wasn't removed and so the
+  next record length was contructed out of data.
+
+Changes in 4.4.3hb
+  27-Jul-2016
+
+* Fix typecmp;
+  don't call typecmp for an explizit FILE list;
+  print a message when files are ignored (because they match one of the file
+  types in the extensions list - in typecmp);
+  change the long name and help text for option -e to make it clearer
+
+Changes in 4.4.3hb
+  3-Mar-2016
+
+* Skip XOR data processing which fixes bugs, which showed as
+  - missing files in the -t aka /list output
+  - "Snark: invalid data header word 0: ddd word 1: ddd"
+  - "Warning: unrecognized record type..."
+
+* Write debug output to stderr
+
+* Re-group selective debug output - undocumented -Dxxx:
+  #define D_BLKREC   0x1
+  #define D_FILE     0x2
+  #define D_VBN      0x4
+  #define D_IO       0x8
+  #define D_SUM	    0x10
+  #define D_TIME    0x20
+  #define D_FILE_X  0x40
+  #define D_VBN_X   0x80
+  #define D_SUM_X  0x100
+  
+* Change/add some debug output for blocks.
+
+* Fix IDENT linker option in build.com.
+
+* Make sure STDIN/OUT/ERR_FILENO is defined for VMS builds.
+
+  22-Aug-2013
+
+* Add a new output option for extracting files.
+
+* Allow stdin and stdout for save sets and output files.
+
+* Adjust usage and allow the listed '?' as option; change
+  the format of the usage line and the grouping of the
+  options.
+
+* In the Makefile, improve handling of vmsbackupver.h and pdf tools.
+
+
 Changes in 4.4.3
   Hoff; http://www.hoffmanlabs.com
   25-Feb-2011
diff --git a/build.com b/build.com
index 816e65f..3498d49 100644
--- a/build.com
+++ b/build.com
@@ -2,7 +2,7 @@ $ write sys$output "Build procedure intended for OpenVMS testing only."
 $ write sys$output "On OpenVMS, use the (real) BACKUP and not this tool."
 $
 $
-$ VBVER = "4.4.3"
+$ VBVER = "4.4.3hb"
 $
 $ if f$locate(",D,",",''p1',") .ne. f$length(",''p1',")
 $ then
@@ -15,7 +15,7 @@ $ endif
 $
 $ close/nolog opt
 $ open/write opt sys$scratch:vmsbackupbld.opt
-$ write opt "IDENTIFICATION=VMSBACK''VBVER'"
+$ write opt "IDENTIFICATION=""VMSBACK''VBVER'"""
 $ close opt
 $ close/nolog ver
 $ open/write ver vmsbackupver.h
diff --git a/getoptmain.c b/getoptmain.c
index d2c5845..5a67289 100644
--- a/getoptmain.c
+++ b/getoptmain.c
@@ -27,25 +27,27 @@ void
 usage (progname)
 char *progname;
 {
-	fprintf (stderr, "Usage:  %s -{tx}[cdevwF][-b blocksize][-s setnumber][-f tapefile]\n",
+	fprintf (stderr, "Usage:  %s [OPTION]... [FILE]...\n",
 		 progname);
         fprintf (stderr, "  Version %s\n", VersionString );
         fprintf (stderr, "  Reads and optionally unpacks OpenVMS BACKUP savesets\n" );
 	// pad the getoptlong text switch lengths to the same for display purposes
-	fprintf(stderr, "\nAvailable switches:\n"
+	fprintf(stderr, "\nMain operation mode:\n"
+            HELPTEXT( "t", "list     ", "List files in saveset" )
+            HELPTEXT( "x", "extract  ", "Extract files" ) );
+	fprintf(stderr, "\nAvailable options:\n"
             HELPTEXT( "b", "blocksize", "Use specified blocksize" )
             HELPTEXT( "B", "binary   ", "Extract as binary files" )
 	    HELPTEXT( "c", "complete ", "Retain complete filename" )
             HELPTEXT( "d", "directory", "Create subdirectories" )
-            HELPTEXT( "e", "extension", "Extract all files" )
+            HELPTEXT( "e", "extensions", "Extract all filename extensions" )
             HELPTEXT( "f", "file     ", "Read from file" )
             HELPTEXT( "F", "full     ", "Full detail in listing" )	    
+            HELPTEXT( "o", "output   ", "Extract to file" )
             HELPTEXT( "s", "saveset  ", "Read saveset number" )
-            HELPTEXT( "t", "list     ", "List files in saveset" )
             HELPTEXT( "v", "verbose  ", "List files as they are processed" )
 	    HELPTEXT( "V", "version  ", "Show program version number" )
             HELPTEXT( "w", "confirm  ", "Confirm files before restoring" )
-            HELPTEXT( "x", "extract  ", "Extract files" )
             HELPTEXT( "?", "help     ", "Display this help message") );
 	return;
 }
@@ -59,8 +61,9 @@ static const struct option OptionListLong[] =
 	{"blocksize", 1, 0, 'b'},
 	{"complete", 0, 0, 'c'},
 	{"directory", 0, 0, 'd'},
-	{"extension", 0, 0, 'e'},
+	{"extensions", 0, 0, 'e'},
 	{"file", 1, 0, 'f'},
+	{"output", 1, 0, 'o'},
 	{"saveset", 1, 0, 's'},
 	{"list", 0, 0, 't'},
 	{"verbose", 0, 0, 'v'},
@@ -99,12 +102,13 @@ char *argv[];
 	flag_binary = 0;
 	flag_full = 0;
 	tapefile = NULL;
+	outfile = NULL;
 
 #ifdef HAVE_GETOPTLONG
-	while((c=getopt_long(argc,argv,"b:cdef:s:tvwxFVBD:",
+	while((c=getopt_long(argc,argv,"b:cdef:o:s:tvwxFVBD:?",
 		OptionListLong, &OptionIndex)) != EOF)
 #else
-	while((c=getopt(argc,argv,"b:cdef:s:tvwxFVBD:")) != EOF)
+	while((c=getopt(argc,argv,"b:cdef:o:s:tvwxFVBD:?")) != EOF)
 #endif
 		switch(c){
 		case 'b':
@@ -122,6 +126,9 @@ char *argv[];
 		case 'f':
 			tapefile = optarg;
 			break;
+		case 'o':
+			outfile = optarg;
+			break;
 		case 's':
 			sflag++;
 			sscanf(optarg,"%d",&selset);
diff --git a/vmsbackup.1 b/vmsbackup.1
index 527fbe2..192033e 100644
--- a/vmsbackup.1
+++ b/vmsbackup.1
@@ -3,9 +3,7 @@
 vmsbackup \- reads and extracts files from within an OpenVMS BACKUP utility 
 saveset file.
 .SH SYNOPSIS
-.B vmsbackup
-.B \-{tx}[cdevwB][s setnumber][f tapefile][b blocksize]
-[ name ... ]
+.B vmsbackup [OPTION]... [FILE]...
 .SH DESCRIPTION
 .I vmsbackup 
 reads an OpenVMS-generated BACKUP saveset or (where available) BACKUP tape, 
@@ -13,6 +11,21 @@ converting the RMS-format files to Unix-format files (where feasible) and
 writing the files to disc.  The default operation of the program is to read
 an entire disc saveset or entire tape saveset, extracting every file and 
 writing it to disc.  This behavior may be modified by the following options.
+.I FILE
+(optional) argument specifies one or more filenames to be
+selectively located within the tape or disc saveset, and processed.
+The name may contain the usual sh(1) meta-characters *?![] \nnn.
+.SH FUNCTION OPTIONS
+.TP 8
+Main operation mode:
+.TP 8
+.B t
+Produce a table of contents (a directory listing) on the standard output
+of the files on tape.
+.TP 8
+.B x
+extract the named files from the disk saveset or the tape.
+.SH OTHER OPTIONS
 .TP 8
 .B b blocksize
 Use blocksize as the blocksize to read the saveset with.
@@ -111,9 +124,8 @@ This must be a raw mode tape device.
 .B s saveset
 Process only the given saveset number.
 .TP 8
-.B t
-Produce a table of contents (a directory listing) on the standard output
-of the files on tape.
+.B o filename
+Extract into the given file.
 .TP 8
 .B v
 Verbose output.
@@ -133,14 +145,6 @@ tool.
 prints the action to be taken followed by file name, then
 wait for user confirmation. If a word beginning with `y'
 is given, the action is done. Any other input means don't do it.
-.TP 8
-.B x
-extract the named files from the disk saveset or the tape.
-.TP 8 
-.I name
-(optional) argument specifies one or more filenames to be
-selectively ocated within the tape or disc saveset, and processed.
-The name may contain the usal sh(1) meta-characters *?![] \nnn.
 .SH EXAMPLES
 .I vmsbackup -t -f saveset.bck
 lists the file contents of the specified BACKUP saveset.
diff --git a/vmsbackup.c b/vmsbackup.c
index 37baf38..4d88df3 100644
--- a/vmsbackup.c
+++ b/vmsbackup.c
@@ -181,6 +181,15 @@
 #  include <unistd.h>
 #  include <fcntl.h>
 #endif
+/*
+ * On VMS these are in unistd.h, which in build.com is not included
+ * as HAVE_UNIXIO_H is defined.
+ */
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0 /* Standard input. */
+# define STDOUT_FILENO 1 /* Standard output. */
+# define STDERR_FILENO 2 /* Standard error output. */
+#endif
 
 #include <stdio.h>
 #include <ctype.h>
@@ -410,6 +419,7 @@ short reclen;
 short fix;
 short recsize;
 unsigned short int VFC_ctr_bytes   = 0;
+int needToSkipVFC = 0;
 
 /* Number of files we have seen.  */
 unsigned int nfiles;
@@ -430,6 +440,10 @@ int fd;  /* tape file descriptor */
 *  ignore everything  starting at the second summary record and
 *  onward.   (This smells vaguely of a BACKUP bug.)
 */
+/* No bug. This happened, when an XORBLOCK was processed as a DATABLOCK
+ * and a record type 1 == summary was found in the XOR data.
+ * For now, XORBLOCKS are skipped.
+ */
 int summary_seen = 0;
 
 
@@ -437,6 +451,8 @@ int summary_seen = 0;
 
 /* The save set that we are listing or extracting.  */
 char *tapefile;
+/* The output file we are extracting into.  */
+char *outfile;
 
 /* We're going to say tflag indicates our best effort at the same
    output format as VMS BACKUP/LIST.  Previous versions of this
@@ -450,8 +466,17 @@ int sflag; // Read saveset number.
 int vflag; // List files as they are processed.
 int wflag; // Confirm files before restoring.
 int xflag; // Extract files.
+int ehint; // Hint for using the eflag when one or more files were ignored
 int debugflags;
-
+#define D_BLKREC   0x1
+#define D_FILE     0x2
+#define D_VBN      0x4
+#define D_IO       0x8
+#define D_SUM	  0x10
+#define D_TIME    0x20
+#define D_FILE_X  0x40
+#define D_VBN_X   0x80
+#define D_SUM_X  0x100
 
 /* Extract files in binary mode.  FIXME: Haven't tried to document
    (here or in the manpage) exactly what that means.  I think it probably
@@ -553,12 +578,12 @@ openfile(char *req_file_name, int struclev)
           }
        } 
 
-       *temp_unix_filename++;
+       temp_unix_filename++;
 
     } // Convert the VMS directory path to Unix format.
 
      // Position the pointer at the end of the file path.
-    *temp_unix_filename++;
+    temp_unix_filename++;
 
     if (!dflag) {
         // Write the output file to the current directory.
@@ -585,9 +610,21 @@ openfile(char *req_file_name, int struclev)
        *temp_unix_filename = '\0';
     }
 
-    if(!eflag && procf) {
-        // Check if this file was requested to be extracted.
+    if(!eflag && procf && !(goptind < gargc)) {
+       // Check if this file should be ignored, because it matches an entry
+       // on the extensions list,
+       // but only if there was no explicit FILE list on the command line
        procf = typecmp(++ext);
+       if (!procf && vflag) {
+          printf("ignoring: %s\n", filename);
+       }
+       if (!procf && !ehint) {
+	       ehint = 1;
+	       printf("one or more files matching the extensions list are ignored,\n"
+		      "consider using the -e/--extensions option\n");
+	       if (!vflag)
+		       printf("or the -v/--verbose option to have the ignored files listed\n");
+       }
     }
 
     if(procf && wflag) {
@@ -604,7 +641,13 @@ openfile(char *req_file_name, int struclev)
 
     if(procf) {
         /* Open the file for writing. */
-       found_file_ftr =  fopen(output_unix_filename, "w");
+       if(outfile)
+	  if(0==strcmp(outfile,"-"))
+	     found_file_ftr = fdopen(STDOUT_FILENO,"w");
+	  else
+	     found_file_ftr =  fopen(outfile, "w");
+       else
+          found_file_ftr =  fopen(output_unix_filename, "w");
 
         // Record the current file name and date.
        strcpy (unix_filename, output_unix_filename);
@@ -629,8 +672,8 @@ int close_file (FILE *out_fptr, char output_filename[256],
 
    status = fclose(out_fptr);
 
-   if (debugflags & 1) {
-      printf ("Closing file: %s status %d\n", output_filename, status); 
+   if (debugflags & D_IO) {
+      fprintf (stderr, "Closing file: %s status %d\n", output_filename, status);
    }
 
    // Set the file access time and modification time if known.
@@ -640,10 +683,10 @@ int close_file (FILE *out_fptr, char output_filename[256],
       utb.modtime = file_mod_date;
       utime (output_filename, &utb);
 
-      if (debugflags & 1)  {
-         printf ("Setting file %s create time to %d\n", 
+      if (debugflags & D_IO)  {
+         fprintf (stderr, "Setting file %s create time to %d\n",
                  output_filename, (int) file_create_date);
-         printf ("Setting file mod time to %d\n",
+         fprintf (stderr, "Setting file mod time to %d\n",
                  (int) file_mod_date);
        }
    }
@@ -652,7 +695,7 @@ int close_file (FILE *out_fptr, char output_filename[256],
 }
 
 int
-typecmp(register char *str)    
+typecmp(register char *str)
   /* Compare the filename type in str with our list of file type 
       to be ignored.  
 
@@ -688,7 +731,6 @@ typecmp(register char *str)
 
     register int    i;
 
-
         i = -1;
         while (*type[++i]) {
                 int foo;
@@ -701,11 +743,8 @@ typecmp(register char *str)
                 foo = strncasecmp(str, type[i],typ_len);
                 if ( foo == 0 ) /* zero is a match; ignore the file */
                      return(0);
-                return(1);      /* default to include file */
         }
-
-   perror("typecmp internal error");
-   exit(1);
+	return 1;      /* default to include file */
  }
 
 
@@ -789,16 +828,16 @@ process_summary (unsigned char *buffer, unsigned short rsize)
         // Get the attribute value.
        text  = ((struct bsa *)&buffer[attr_ptr])->bsa_dol_t_text;
 
-       if ( debugflags & 1 ) {
-          printf ("\n--process_summary debug_dump\n");
+       if ( debugflags & D_SUM ) {
+          fprintf (stderr, "\n--process_summary debug_dump\n");
           debug_dump(text, dsize, type);
-          printf ("--Processing summary record %d type = %d size = %d\n", 
+          fprintf (stderr, "--Processing summary record %d type = %d size = %d\n",
                   attr_ptr, type, dsize);
        }
 
        if ( !dsize ) {
-          if ( debugflags & 1 ) {
-             printf ("\nnull dsize; slamming the record type code.\n");
+          if ( debugflags & D_SUM ) {
+             fprintf (stderr, "\nnull dsize; slamming the record type code.\n");
  	  }
          type = 0;
 	}
@@ -874,8 +913,8 @@ process_summary (unsigned char *buffer, unsigned short rsize)
                       break;
 
                    default:
-		     if ( debugflags & 1 ) {
-                        printf("Unknown OS Code = %d\n", oscode );
+		     if ( debugflags & D_SUM ) {
+                        fprintf(stderr, "Unknown OS Code = %d\n", oscode );
                      }
 
                      os = "Unknown OS Code";
@@ -942,8 +981,8 @@ process_summary (unsigned char *buffer, unsigned short rsize)
              vol_set_name      = (char *)text;
              vol_set_name_size = dsize;
 
-	     if (debugflags & 8) {
-                printf("BSA$K_VOLSETNAM: %s dsize = %d\n", 
+	     if (debugflags & D_SUM_X) {
+                fprintf(stderr, "BSA$K_VOLSETNAM: %s dsize = %d\n",
                        vol_set_name, dsize);
              }
              break;
@@ -955,8 +994,8 @@ process_summary (unsigned char *buffer, unsigned short rsize)
                 num_vols = getu16 (text);
              }
 
-	     if (debugflags & 8) {
-                printf("BSA$K_NVOLS: %d dsize = %d\n", num_vols, dsize);
+	     if (debugflags & D_SUM_X) {
+                fprintf(stderr, "BSA$K_NVOLS: %d dsize = %d\n", num_vols, dsize);
              }
 
              break;
@@ -967,8 +1006,8 @@ process_summary (unsigned char *buffer, unsigned short rsize)
                 backup_size = getu16 (text);
              }
 
-	     if (debugflags & 8) {
-                printf("BSA$K_BACKSIZE: %d dsize = %d\n", backup_size, dsize);
+	     if (debugflags & D_SUM_X) {
+                fprintf(stderr, "BSA$K_BACKSIZE: %d dsize = %d\n", backup_size, dsize);
              }
              break;
 
@@ -976,8 +1015,8 @@ process_summary (unsigned char *buffer, unsigned short rsize)
              num_files = getu16 (text);
 
 	      // Get the number of files in the save set.
-	     if (debugflags & 8) {
-                printf("BSA$K_BACKFILES: dsize = %d\n", dsize);
+	     if (debugflags & D_SUM_X) {
+                fprintf(stderr, "BSA$K_BACKFILES: dsize = %d\n", dsize);
              }
              break;
 
@@ -985,8 +1024,8 @@ process_summary (unsigned char *buffer, unsigned short rsize)
               /* Silently ignore any unrecognized attribute codes,
                  allowing for future changes to BACKUP.
               */
-	     if (debugflags & 8) {
-                printf("BSA Unrecognized BSA_K backup record attribute: %d, dsize = %d\n", 
+	     if (debugflags & D_SUM_X) {
+                fprintf(stderr, "BSA Unrecognized BSA_K backup record attribute: %d, dsize = %d\n",
                        type, dsize);
              }
              break;
@@ -1168,14 +1207,14 @@ process_file (unsigned char *buffer, unsigned short int rsize)
 
        data = ((struct bsa *)&buffer[c])->bsa_dol_t_text;
 
-       if ( debugflags ) {
-          printf ("\n--process_file: file attribute record debug_dump.\n");
+       if ( debugflags & D_FILE ) {
+          fprintf (stderr, "\n--process_file: file attribute record debug_dump.\n");
           debug_dump(data, dsize, dtype);
        }
 
        if ( !dsize ) {
-          if ( debugflags & 1 ) {
-             printf ("\nnull file attribute dsize; slamming the type code.\n");
+          if ( debugflags & D_FILE ) {
+             fprintf (stderr, "\nnull file attribute dsize; slamming the type code.\n");
           }
          dtype = 0;
         }
@@ -1184,8 +1223,8 @@ process_file (unsigned char *buffer, unsigned short int rsize)
        switch (dtype) {
 
           case 0:
-            if ( debugflags & 8 ) {
-               printf ("null file attribute dtype; ignoring this record.\n");
+            if ( debugflags & D_FILE_X ) {
+               fprintf (stderr, "null file attribute dtype; ignoring this record.\n");
             }
  	    break;
 
@@ -1565,7 +1604,7 @@ process_file (unsigned char *buffer, unsigned short int rsize)
 
           default:
               /* unexpected or unrecognized code */
-	     if ( debugflags & 8 )
+	     if ( debugflags & D_FILE_X )
 	         sprintf(attrib_proc, 
                     "Unrecognized or unexpected BSA_K record attribute type code:  0x%x/%d\n", 
                     dtype, dtype);
@@ -1574,8 +1613,8 @@ process_file (unsigned char *buffer, unsigned short int rsize)
 
        } /* Record the file attributes in this record.  */
 
-       if (debugflags & 1) {
-          printf("Processing %s\n", attrib_proc);
+       if (debugflags & D_FILE) {
+          fprintf(stderr, "Processing %s\n", attrib_proc);
        }
 
        c += dsize + 4;
@@ -1583,28 +1622,28 @@ process_file (unsigned char *buffer, unsigned short int rsize)
     } /* Process the File attribute record. */
 
 
-    if (debugflags == 3) {
-       printf("filename = %s\n", filename );
-       printf(" Record format:           %d\n", recfmt);
-       printf("  Record type:            %d\n", 
+    if (debugflags & D_FILE) {
+       fprintf(stderr, "filename = %s\n", filename );
+       fprintf(stderr, " Record format:           %d\n", recfmt);
+       fprintf(stderr, "  Record type:            %d\n",
               rec_type.rec_type_word.rectype_bits.rtype);
-       printf("  File organization:      %d\n", 
+       fprintf(stderr, "  File organization:      %d\n",
               rec_type.rec_type_word.rectype_bits.fileorg);
-       printf(" Record attributes:       %d\n", recatt);
-       printf(" Record size:             %d\n", recsize);
-       printf(" Highest block:           %d\n", (int) highest_VBN);
-       printf(" End of file block:       %d\n", (int) eof_VBN);
-       printf(" End of file byte:        %d\n", first_free_byte);
-       printf(" Bucket size:             %d\n", bucket_size);
-       printf(" Fixed control area size: %d\n", VFC_ctr_bytes);
-       printf(" Maximum record size:     %d\n", max_rec_size);
-       printf(" Default extension size:  %d\n", def_extend_quan);
-       printf(" Global buffer count:     %d\n", global_buf_cnt);
-       printf(" Directory version limit  %d\n", att_file_ver_limit);
+       fprintf(stderr, " Record attributes:       %d\n", recatt);
+       fprintf(stderr, " Record size:             %d\n", recsize);
+       fprintf(stderr, " Highest block:           %d\n", (int) highest_VBN);
+       fprintf(stderr, " End of file block:       %d\n", (int) eof_VBN);
+       fprintf(stderr, " End of file byte:        %d\n", first_free_byte);
+       fprintf(stderr, " Bucket size:             %d\n", bucket_size);
+       fprintf(stderr, " Fixed control area size: %d\n", VFC_ctr_bytes);
+       fprintf(stderr, " Maximum record size:     %d\n", max_rec_size);
+       fprintf(stderr, " Default extension size:  %d\n", def_extend_quan);
+       fprintf(stderr, " Global buffer count:     %d\n", global_buf_cnt);
+       fprintf(stderr, " Directory version limit  %d\n", att_file_ver_limit);
 
        if ( strucvalid ) {
-          printf(" Structure version:       %d\n", strucver);
-          printf(" Structure level:         ODS-%d\n\n", struclev);
+          fprintf(stderr, " Structure version:       %d\n", strucver);
+          fprintf(stderr, " Structure level:         ODS-%d\n\n", struclev);
        }
     }
 
@@ -1632,10 +1671,10 @@ process_file (unsigned char *buffer, unsigned short int rsize)
        exit( 1 );
      }
 
-    if (debugflags & 1)  {
-       printf("Number of blocks = %lld, Highest block = %d, first free block = %d\n", 
+    if (debugflags & D_FILE)  {
+       fprintf(stderr, "Number of blocks = %lld, Highest block = %d, first free block = %d\n",
               nblk, highest_VBN_high, first_free_byte);
-       printf("File Size: 0x%llx/%lld, Allocated File Size Calc:%lld Recorded:%d\n", 
+       fprintf(stderr, "File Size: 0x%llx/%lld, Allocated File Size Calc:%lld Recorded:%d\n",
               filesize, filesize, allocated_bytes_file_size, (int) alloc_file_size);
     }
 
@@ -1858,7 +1897,11 @@ process_file (unsigned char *buffer, unsigned short int rsize)
 
 
        if ( fptr_out!= NULL && vflag) {
-          printf("extracting: %s\n        to: %s\n", 
+    	  if (outfile)
+    		  printf("extracting: %s\n        to: %s\n",
+    				  filename, outfile);
+    	  else
+    		  printf("extracting: %s\n        to: %s\n",
                  filename, unix_filename);
        }
 
@@ -1888,15 +1931,15 @@ process_vbn(unsigned char *buffer, unsigned short rsize)
 
     i = 0;
 
-    if (debugflags & 1) {
-       printf ("Writing output file %s count: %d, size: %lld, recsize: %d\n", 
+    if (debugflags & D_VBN) {
+       fprintf (stderr, "Writing output file %s count: %d, size: %lld, recsize: %d\n",
                unix_filename, file_byte_count, filesize, rsize);
     }
 
     while ((file_byte_count+i < filesize) && (i < rsize)) {
 
-       if (debugflags == 2) {
-            printf("Variable-length record code: 0x0%x\n", 
+       if (debugflags & D_VBN) {
+            fprintf(stderr, "Variable-length record code: 0x0%x\n",
 		rec_type.rec_type_word.rectype_bits.rtype );
        }
 
@@ -1904,8 +1947,8 @@ process_vbn(unsigned char *buffer, unsigned short rsize)
        switch (rec_type.rec_type_word.rectype_bits.rtype) {
 
           case FAB_C_FIX: 	/* FAB$C_FIX - fixed-length record format.*/
-	     if (debugflags == 1) {
-                printf("Writing fixed-length records\n");
+	     if (debugflags & D_VBN_X) {
+                fprintf(stderr, "Writing fixed-length records\n");
              }
 
              if (reclen == 0) {
@@ -1918,17 +1961,27 @@ process_vbn(unsigned char *buffer, unsigned short rsize)
              break;
 
           case FAB_C_VAR: /* FAB$C_VAR - variable-length record format. */
-	     if (debugflags == 2) {
-                printf("Writing variable-length records\n");
+	     if (debugflags & D_VBN_X) {
+                fprintf(stderr, "Writing variable-length records\n");
              }
 
           case FAB_C_VFC: /* FAB$C_VFC - variable-length with fixed-length
                                          control record format. This format is
                                          not supported for indexed files.*/
-	     if (debugflags == 2) {
-                printf("Writing VAR/VFC records\n");
+	     if (debugflags & D_VBN_X) {
+                fprintf(stderr, "Writing VAR/VFC records\n");
              }
-
+	     	 if (needToSkipVFC) {
+                 if (flag_binary) { // && rec_type.rec_type_word.rectype_bits.rtype == FAB_C_VFC is true otherwise needToSkipVFC would be false
+		         // If binary mode requested just write the data out.
+                    for (j = 0; j < VFC_ctr_bytes; j++) {
+                       fputc (buffer[i+j], fptr_out);
+                    }
+                 }
+	     		 needToSkipVFC = 0;
+	     		 i += VFC_ctr_bytes;
+	     		 reclen -= VFC_ctr_bytes;
+	     	 }
              if (reclen <= 0) {
 	         // Get the record length from the buffer.
                 reclen = getu16 (&buffer[i]);
@@ -1950,6 +2003,11 @@ process_vbn(unsigned char *buffer, unsigned short rsize)
 
                 i += 2; // Skip over the next two bytes.
 
+                if (i >= rsize) {
+                	needToSkipVFC = 1;
+                	break;
+                }
+
                 if (rec_type.rec_type_word.rectype_bits.rtype == FAB_C_VFC) {
                    if (flag_binary) {
 		       // If binary mode requested just write the data out.
@@ -1964,6 +2022,9 @@ process_vbn(unsigned char *buffer, unsigned short rsize)
 		    // Decrement the record length by the number of bytes 
                     //  already written.
                    reclen -= VFC_ctr_bytes;
+                   if (i >= rsize)
+                	   break;
+
                 }
    
 	     } else if ((reclen == fix) && (recatt == FAB_M_FTN)) {
@@ -2012,18 +2073,18 @@ process_vbn(unsigned char *buffer, unsigned short rsize)
        case FAB_C_STM: /* FAB$C_STM - stream record format. Records are  
                                       delimited by FF, VT, LF or CR LF, and all
                                       leading zeros are ignored.*/
-	  if (debugflags == 1) {
-             printf("Writing STM records\n");
+	  if (debugflags & D_VBN_X) {
+             fprintf(stderr, "Writing STM records\n");
           }
 
        case FAB_C_STMLF: /* FAB$C_STMLF - stream sequential with linefeed; 
                                           used by C and Unix */
-	  if (debugflags == 1) {
-             printf("Writing STMLF records\n");
+	  if (debugflags & D_VBN_X) {
+             fprintf(stderr, "Writing STMLF records\n");
           }
 
           if (reclen < 0) {
-             printf("Error - Negative record length %d\n", reclen);
+             fprintf(stderr, "Error - Negative record length %d\n", reclen);
           }
 
           if (reclen == 0) {
@@ -2046,8 +2107,8 @@ process_vbn(unsigned char *buffer, unsigned short rsize)
        case FAB_C_STMCR: /* FAB$C_STMCR - stream sequential with carriage 
                                           control */
 
-	  if (debugflags == 1) {
-             printf("Writing STMCR records\n");
+	  if (debugflags & D_VBN_X) {
+             fprintf(stderr, "Writing STMCR records\n");
           }
 
           c = buffer[i++];
@@ -2100,6 +2161,8 @@ process_block(unsigned char *block, int file_blocksize)
 
     unsigned long  bsize;
     unsigned long  buff_ptr = 0;
+    unsigned short int  bapplic;
+
 
      // VMS backup block header.
     struct bbhdef *block_header;
@@ -2145,15 +2208,56 @@ process_block(unsigned char *block, int file_blocksize)
        exit(1);
     }
 
-    if (debugflags & 1) {
-       printf("new block: i = %d, bsize = %d\n", (int) buff_ptr, (int) bsize);
-    }
+    bapplic = getu16 (block_header->bbh_dol_w_applic);
+    if (debugflags & D_BLKREC) {
+#define STRINGIFY(m) #m
+       unsigned short int bopsys, bsubsys;
+	   unsigned long bnumber;
+       char *copsys, *csubsys, *capplic;
+       bnumber = getu32 (block_header->bbh_dol_l_number);
+       fprintf(stderr, "\nblock header\n file offset   = 0x%x\n size          = %d\n",
+    		   (bnumber-1)*bsize, (int) bsize);
+       bopsys = getu16 (block_header->bbh_dol_w_opsys);
+       switch (bopsys) {
+       case	BACKUP_K_OPSYS_VAX: copsys = &STRINGIFY(BACKUP_K_OPSYS_VAX)[15];
+    		   break;
+       case	BACKUP_K_OPSYS_ALPHA: copsys = &STRINGIFY(BACKUP_K_OPSYS_ALPHA)[15];
+    		   break;
+       case	BACKUP_K_OPSYS_IA64: copsys = &STRINGIFY(BACKUP_K_OPSYS_IA64)[15];
+    		   break;
+       default: copsys = "unknown";
+    		   break;
+
+       }
+       bsubsys = getu16 (block_header->bbh_dol_w_subsys);
+       switch (bsubsys) {
+       case	BACKUP$K_BACKUP: csubsys = &STRINGIFY(BACKUP$K_BACKUP)[9];
+    		   break;
+       default: csubsys = "unknown";
+    		   break;
+
+       }
+       switch (bapplic) {
+       case	BACKUP$K_DATABLOCK: capplic = &STRINGIFY(BACKUP$K_DATABLOCK)[9];
+    		   break;
+       case	BACKUP$K_XORBLOCK: capplic = &STRINGIFY(BACKUP$K_XORBLOCK)[9];
+    		   break;
+       default: capplic = "unknown";
+    		   break;
 
+       }
+       fprintf(stderr, " opsys         = %d (%s)\n subsys        = %d (%s)\n applic        = %d (%s)\n",
+    		   bopsys, copsys, bsubsys, csubsys, bapplic, capplic);
+       fprintf(stderr, " number        = %d\n", bnumber);
+    }
+    /* skip an XORBLOCK */
+    if (bapplic==BACKUP$K_XORBLOCK)
+    	return;
      /* Read the records. */
     while (buff_ptr < bsize) {
         /* Read the backup record header. */
-       if (debugflags & 1) {
-          printf("\nrecord header\n");
+       if (debugflags & D_BLKREC) {
+          fprintf(stderr, "\nrecord header\n");
        }
 
        record_header = (struct brhdef *) &block[buff_ptr];
@@ -2167,35 +2271,35 @@ process_block(unsigned char *block, int file_blocksize)
         // Get the record type.
        rtype = getu16 (record_header->brh_dol_w_rtype);
 
-       if (debugflags & 1) {
-          printf(" block at byte = %d\n", (int) buff_ptr);
-          printf(" record type   = %d\n",   rtype);
-          printf(" record size   = %d (bytes)\n",   rsize);
-          printf(" record flags  = 0x%x\n", 
+       if (debugflags & D_BLKREC) {
+          fprintf(stderr, " block offset  = 0x%x\n", (int) buff_ptr);
+          fprintf(stderr, " rsize         = %d (bytes)\n",   rsize);
+          fprintf(stderr, " type          = %d\n",   rtype);
+          fprintf(stderr, " flags         = 0x%x\n",
                  (int) getu32 (record_header->brh_dol_l_flags));
-          printf(" data address  = 0x%x\n",  
+          fprintf(stderr, " address       = 0x%x\n",
                  (int) getu32 (record_header->brh_dol_l_address));
-          printf(" block flags   = 0x%x\n", 
+          fprintf(stderr, " blockflags    = 0x%x\n",
                  (int) getu32 (record_header->brh_dol_l_blockflags));
        }
 
     
-       if (debugflags & 1) {
-          printf(" rtype         = ");
+       if (debugflags & D_BLKREC) {
+          fprintf(stderr, " rtype         = ");
        }
        switch (rtype) { /* Process each DOL record type. */
 
           case brh_dol_k_null:
-	     if (debugflags & 1) {
-                printf("null\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "null\n");
              }
 
               /* This is the type used to pad to the end of a block.  */
              break;
 
           case brh_dol_k_summary:
-	     if (debugflags & 1) {
-                printf("summary\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "summary\n");
              }
 
               /* there can be only one; ignore the rest. */
@@ -2209,16 +2313,16 @@ process_block(unsigned char *block, int file_blocksize)
 
           case brh_dol_k_file:
                /* Process file attributes. */
-	     if (debugflags & 1) {
-                printf("file\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "file\n");
              }
 
              process_file(&block[buff_ptr], rsize);
              break;
 
           case brh_dol_k_vbn:
-	     if (debugflags & 1) {
-                printf("vbn\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "vbn\n");
              }
 
               // Process a virtual block record (file record).
@@ -2226,44 +2330,44 @@ process_block(unsigned char *block, int file_blocksize)
              break;
 
           case brh_dol_k_physvol:
-	     if (debugflags & 1) {
-                printf("physvol\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "physvol\n");
              }
              break;
 
           case brh_dol_k_lbn:
-	     if (debugflags & 1) {
-                printf("lbn\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "lbn\n");
              }
              break;
 
           case brh_dol_k_fid:
-	     if (debugflags & 1) {
-                printf("fid\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "fid\n");
              }
              break;
 
           case brh_dol_k_file_ext:
-	     if (debugflags & 1) {
-                printf("file_ext (unsupported)\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "file_ext (unsupported)\n");
              }
              break;
 
           case brh_dol_k_lbn_576:
-	     if (debugflags & 1) {
-                printf("lbn_576 (unsupported)\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "lbn_576 (unsupported)\n");
              }
              break;
 
           case brh_dol_k_rs_dirattr:
-	     if (debugflags & 1) {
-                printf("rs_dirattr (unsupported)\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "rs_dirattr (unsupported)\n");
              }
              break;
 
           case brh_dol_k_alias:
-	     if (debugflags & 1) {
-                printf("alias (unsupported)\n");
+	     if (debugflags & D_BLKREC) {
+                fprintf(stderr, "alias (unsupported)\n");
              }
              break;
 
@@ -2272,11 +2376,11 @@ process_block(unsigned char *block, int file_blocksize)
               **  It is quite possible that we should just skip
               **  this without even printing a warning. 
               */
-             if (debugflags & 8) {
+             if (debugflags & D_BLKREC) {
                 fprintf (stderr, " Warning: unrecognized record type\n");
                 fprintf (stderr, " Allowed record types: 0 to %d\n", 
-                         brh_dol_k_max_rtype);
-                fprintf (stderr, " record type: %d, size: %d\n",
+                         brh_dol_k_max_rtype-1);
+                fprintf (stderr, " rtype: %d, rsize: %d\n",
                          rtype, rsize);
              }
              break;
@@ -2284,9 +2388,12 @@ process_block(unsigned char *block, int file_blocksize)
        } /* Process each record type. */
 
        if ( summary_seen > 1 ) {
-	  if ( debugflags ) {
-             printf("summary processed; completed execution\n");
-          }
+          /*
+          ** This shouldn't happen and it may be better to terminate with
+          ** a proper exit code.
+          */
+          summary_seen = 1;
+          fprintf(stderr, "secondary summary record found: rest of block skipped\n");
           break;
        }
 
@@ -2332,20 +2439,20 @@ rdhead(unsigned char *block, int *rec_blocksize)
        label_count += 1;
 
        if (strncmp(label, "VOL1",4) == 0) {
-	  if (debugflags & 1) {
-             printf ("\nFirst Volume Label:\n%s\n", label);
+	  if (debugflags & D_IO) {
+             fprintf (stderr, "\nFirst Volume Label:\n%s\n", label);
           }
 
           sscanf(label+4, "%17s", vol_name);
 
           if (vflag || tflag) { 
-             printf("Volume: %s\n", vol_name);
+             fprintf(stderr, "Volume: %s\n", vol_name);
           }
        }
 
        if (strncmp(label, "HDR1",4) == 0) {
-	  if (debugflags & 1) {
-             printf ("\nFirst Header Label: \n%s\n", label);
+	  if (debugflags & D_IO) {
+             fprintf (stderr, "\nFirst Header Label: \n%s\n", label);
           }
 
           sscanf(label+4, "%14s", hdr1_name);
@@ -2354,8 +2461,8 @@ rdhead(unsigned char *block, int *rec_blocksize)
 
         /* Get the block size. */
        if (strncmp(label, "HDR2", 4) == 0) {
-          if (debugflags & 1) {
-             printf ("\nSecond Header Label:\n %s\n", label);
+          if (debugflags & D_IO) {
+             fprintf (stderr, "\nSecond Header Label:\n %s\n", label);
           }
 
           nfound = 0;
@@ -2366,19 +2473,19 @@ rdhead(unsigned char *block, int *rec_blocksize)
           }
 
           sscanf(label+5, "%5d", &max_rec_size);
-          if (debugflags & 1) {
-             printf("Max rec size = %d\n", max_rec_size);
+          if (debugflags & D_IO) {
+             fprintf(stderr, "Max rec size = %d\n", max_rec_size);
           }
 
           sscanf(label+10, "%5d", &max_block_size);
-          if (debugflags & 1) {
-             printf("Max block size = %d\n", max_block_size);
+          if (debugflags & D_IO) {
+             fprintf(stderr, "Max block size = %d\n", max_block_size);
           }
        }
     } /* Read the tape label - 4 records of 80 bytes. */
 
-    if (debugflags & 1) {
-       printf ("Read %d labels\n", label_count);
+    if (debugflags & D_IO) {
+       fprintf (stderr, "Read %d labels\n", label_count);
     }
 
     if ((vflag || tflag) && !nfound) {
@@ -2476,7 +2583,10 @@ vmsbackup()
 #endif
 
     /* Open the backup device. */
-    fd = open(tapefile, O_RDONLY);
+    if (0==strcmp(tapefile,"-"))
+       fd = dup(STDIN_FILENO);
+    else
+       fd = open(tapefile, O_RDONLY);
     if (fd < 0) {
        printf ("Error accessing tape drive: ");
        fflush (stdout);
@@ -2491,8 +2601,8 @@ vmsbackup()
     op.mt_op    = MTREW;
     op.mt_count = 1;
 
-    if ( debugflags ) {
-       printf("determining disk or tape; attempting rewind\n");
+    if ( debugflags & D_IO) {
+       fprintf(stderr, "determining disk or tape; attempting rewind\n");
     }
 
     i = ioctl(fd, MTIOCTOP, &op);
@@ -2501,8 +2611,8 @@ vmsbackup()
        if (errno == EINVAL || errno == ENOTTY) {
           ondisk = 1;
 
-	  if ( debugflags ) {
-             printf("Reading from disk\n");
+	  if ( debugflags & D_IO) {
+             fprintf(stderr, "Reading from disk\n");
           }
 
        } else {
@@ -2514,8 +2624,8 @@ vmsbackup()
        }
     }
      
-    if ( debugflags ) {
-       printf("IOCTL rewind status = %d\n", i);
+    if ( debugflags & D_IO) {
+       fprintf(stderr, "IOCTL rewind status = %d\n", i);
     }
 
 #else
@@ -2715,25 +2825,25 @@ static void debug_dump(const unsigned char* buffer, unsigned short int dsize,
     // Determine the maximum number of bits that can be dumped.
     max_dump_size = (long long)buffer + sizeof(buffer) * 8;
 
-    if (debugflags & 1) {
+    if (debugflags) {
        char comma = ' ';
 
-       printf("debug_dump: sizeof(buffer): %d, dsize: 0x%x/%u, dtype: 0x%x/%d: \n        ", 
+       fprintf(stderr, "debug_dump: sizeof(buffer): %d, dsize: 0x%x/%u, dtype: 0x%x/%d: \n        ",
               (int) sizeof (buffer), dsize, dsize, dtype, dtype);
 
        while ((dsize-- > 0) && ((long long)buffer < max_dump_size)) {
-          printf("%c 0x%x/%d", comma, (int) *buffer, (int) *buffer);
+          fprintf(stderr, "%c 0x%x/%d", comma, (int) *buffer, (int) *buffer);
           buffer++;
           comma = ',';
 
 	  cur_dump_dsize++;
           if (!(cur_dump_dsize & 0x07)) {
-             printf(",\n        ");
+             fprintf(stderr, ",\n        ");
              comma = ' ';
           }
        }
 
-       printf("\n\n");
+       fprintf(stderr, "\n\n");
     }
  }
 
@@ -2757,17 +2867,17 @@ time_vms_to_unix(unsigned long long vms_time_ll)
     timezone = 0;
 #endif
 
-    if (debugflags & 16) {
-       printf("time_vms_to_unix()     OpenVMS time in seconds (input) = %lld\n",
+    if (debugflags & D_TIME) {
+       fprintf(stderr, "time_vms_to_unix()     OpenVMS time in seconds (input) = %lld\n",
               vms_time_ll);
-       printf("                       daylight %d, timezone %d, altzone %d\n",
+       fprintf(stderr, "                       daylight %d, timezone %d, altzone %d\n",
               daylight, (int) timezone, altzone );
     }
 
     byte_swapped_ll = getu64((unsigned char *)&vms_time_ll);
 
-    if (debugflags & 16) {
-       printf("                       OpenVMS time in seconds (swizzled) = %lld\n", 
+    if (debugflags & D_TIME) {
+       fprintf(stderr, "                       OpenVMS time in seconds (swizzled) = %lld\n",
               byte_swapped_ll);
     }
 
@@ -2817,15 +2927,15 @@ time_vms_to_unix_asc( unsigned char *vmstime,   int vmstim_len,
      // On a 64 bit machine the VMS time is a Quadword integer.
     unsigned long long int vms_time_ll = 0;
 
-     if (debugflags & 16) {
-        printf("time_vms_to_unix_asc() size of long long int = %lld\n", (long long) sizeof(vms_time_ll));
-        printf("                       size of char string = %lld\n", (long long) sizeof(vmstime));
+     if (debugflags & D_TIME) {
+        fprintf(stderr, "time_vms_to_unix_asc() size of long long int = %lld\n", (long long) sizeof(vms_time_ll));
+        fprintf(stderr, "                       size of char string = %lld\n", (long long) sizeof(vmstime));
      }
 
      memcpy(&vms_time_ll, vmstime, vmstim_len);
   
-     if (debugflags & 16) {
-        printf("                       OpenVMS time in seconds = %lld\n",
+     if (debugflags & D_TIME) {
+        fprintf(stderr, "                       OpenVMS time in seconds = %lld\n",
                vms_time_ll);
      }
 
@@ -2849,8 +2959,8 @@ time_vms_to_unix_asc( unsigned char *vmstime,   int vmstim_len,
      unix_time = time_vms_to_unix( vms_time_ll );
      strftime( date_text, 24, "%d-%b-%Y %H:%M:%S", localtime(&unix_time) );
 
-     if (debugflags & 16) {
-        printf("                       OpenVMS date = %s\n", date_text);
+     if (debugflags & D_TIME) {
+        fprintf(stderr, "                       OpenVMS date = %s\n", date_text);
      }
 
      if ( date_text_len ) {
diff --git a/vmsbackup.h b/vmsbackup.h
index 299606d..b2ef943 100644
--- a/vmsbackup.h
+++ b/vmsbackup.h
@@ -5,6 +5,7 @@ extern int cflag, dflag, eflag, sflag, tflag, vflag, wflag, xflag, debugflags;
 extern int flag_binary;
 extern int flag_full;
 extern char *tapefile;
+extern char *outfile;
 extern int selset;
 extern int blocksize;
 
diff --git a/vmsconstants.h b/vmsconstants.h
index 70bbc38..fc6ae3e 100644
--- a/vmsconstants.h
+++ b/vmsconstants.h
@@ -90,6 +90,9 @@
 #define BACKUP_K_OPSYS_VAX 	0x0400       	/* OpenVMS VAX */
 #define BACKUP_K_OPSYS_ALPHA 	0x0800		/* OpenVMS Alpha */
 #define BACKUP_K_OPSYS_IA64	0x01000		/* OpenVMS I64 */
+#define BACKUP$K_BACKUP 1		/* Subsystem ID */
+#define BACKUP$K_DATABLOCK 1	/* Application ID normal blocks */
+#define BACKUP$K_XORBLOCK 2		/* Application ID XOR blocks */
 
 /* BACKUP summary record attribute codes.  */
 
