
#ifdef __DECC
#pragma module DISKREADER "V01-00"
#else
#module DISKREADER "V01-00"
#endif

/* The second notice comes from sys$examples:gktest.c (OpenVMS 7.0)*/

/*
** COPYRIGHT (c) 1993 BY
** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.
** ALL RIGHTS RESERVED.
**
** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
** ONLY  IN  ACCORDANCE  OF  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR  ANY  OTHER
** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
** OTHER PERSON.  NO TITLE TO AND  OWNERSHIP OF THE  SOFTWARE IS  HEREBY
** TRANSFERRED.
**
** THE INFORMATION IN THIS SOFTWARE IS	SUBJECT TO CHANGE WITHOUT NOTICE
** AND	SHOULD	NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
** CORPORATION.
**
** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE  OR  RELIABILITY OF ITS
** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
*/

/*
**
**  INCLUDE FILES
**
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <iodef.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <ssdef.h>
#include <descrip.h>
#include <rms.h>
#include <starlet.h>
#include <lib$routines.h>

/*
**  Turn off data alignment on Alpha
*/
#ifdef __ALPHA
#pragma nomember_alignment
#endif

/*
**
**  MACRO DEFINITIONS
**
*/
/*
**  Symbolic Parameters
*/

#define BLOCK_SIZE 512

/*
**  VMS Status evaluation macros
*/
#define status_is_ok(sts) ((sts) & 1)
#define status_is_bad(sts) (!((sts) & 1))
#define insure_ok(sts) if (!((sts) & 1)) {lib$signal((sts)); sys$exit((sts));}

/*
**  Global Static data
*/
static char buf[BLOCK_SIZE];
static int buffer_size;
static int end_of_file;
static int final_write_size;	/* Size of the final write, if different */

static struct FAB srcfab;	/* Declare FAB and RAB for the file */
static struct RAB srcrab;

/*
**  Statistics
*/
static int buffer_reads;


/*
**  Function Prototypes
*/

/*
**  Main Entry Point - read a CD-ROM; device must be mounted foreign
*/
void main (
    int argc,
    char **argv )
{
    int argi;
    int rms_status,brd,diskimage;
    char *source_dev = "dka400:";
    char *outfile = "cdout.dat";

    /*
    **	Set defaults
    */
    final_write_size = 0;

    if (argc == 1)
	{
	fprintf (stderr,
	    "DISKREADER - using all defaults, use -help option for help\n");
	fprintf (stderr,
	    "Reading from device dka400: - writing to file cdout.dat\n");
	}

    for(argi=1; argi<argc; argi++)
	{
	if (strcmp(argv[argi], "-o") == 0)
	    {
	    argi++;
	    if (argi<argc)
		{
		outfile=argv[argi];
		}
	    else
		{
                /*
                **  They specified -o without anything following
                */
                fprintf (stderr, "-o must be followed by a file specification.\n");
                exit(1);
                }
	    }
	else if (strcmp(argv[argi], "-i") == 0)
	    {
	    argi++;
	    if (argi<argc)
            {
	    source_dev=argv[argi];
	    }
	    else
	    {                /*
                **  They specified -i without anything following
                */
                fprintf (stderr, "-i must be followed by a device specification.\n");
                exit(1);
                }
	    }
	    else if ((strcmp(argv[argi], "-help") == 0)
	       ||(strcmp(argv[argi], "-h") == 0)
	       ||(strcmp(argv[argi], "-?") == 0))
	    {
	    fprintf (stderr,
		"Usage: cdreader [options] \nOptions are:\n");
	    fprintf (stderr,
		"    -o filename define output-filename, default: cdout.dat)\n");
	    fprintf (stderr,
		"    -i source_dev define source-device, default: dka400:)\n");
	    fprintf (stderr,
		"    -help      (Display this message)\n");
	    exit(0);
	    }
	else
	{
            /*
            **  Unrecognized option
            */
            fprintf (stderr, "%s is not a recognized option.\n",
                argv[argi]);
            exit(1);
            }
	}

    /*
    **	Open the Source
    */
    srcfab = cc$rms_fab;
    srcfab.fab$b_fac = FAB$M_GET | FAB$M_BIO;

    srcfab.fab$l_fna = source_dev;
    srcfab.fab$b_fns = strlen(source_dev);

    srcfab.fab$l_fop = FAB$M_SQO;   /* Sequential only */
		 /*  | FAB$M_NFS;   /* Non file structured */

    srcfab.fab$w_mrs = 0;
    srcfab.fab$b_org = FAB$C_SEQ;

    srcfab.fab$b_shr = FAB$M_NIL;

    rms_status = sys$open (&srcfab, NULL, NULL);
    insure_ok(rms_status);

    srcrab = cc$rms_rab;
    srcrab.rab$l_fab = &srcfab;
    srcrab.rab$l_rop = RAB$M_BIO;
    srcrab.rab$b_mbc = 1;
    srcrab.rab$w_isi = 0;
    rms_status = sys$connect(&srcrab, NULL, NULL);
    insure_ok(rms_status);

    buffer_size = BLOCK_SIZE; 
    end_of_file = FALSE;

    buffer_reads = 0;

/* create output-file */

    diskimage = creat(outfile, O_RDWR,"ctx=stm","mbc=64");
    if(diskimage < 0) {
                        perror("cdout.dat error");
                        abort();
                      }
    /*
    **	Read loop
    **
    **	This loop keeps filling buffers which are being emptied in the
    **	background by the issue_cdr_write/cdr_write_ast routines.
    */
    while(!end_of_file)
	{
	/*
	**  Wait until we have some buffers to fill
	*/
	/*
	**  Start filling buffers again
	*/
	/*
	**  Set the buffer to point to the next available buffer
	*/
	srcrab.rab$l_rop = RAB$M_BIO;
	srcrab.rab$l_ubf = &buf[0];
	srcrab.rab$w_usz = buffer_size;

	/*
	**  Issue the read
	*/
	rms_status = sys$read(&srcrab, NULL, NULL);

	/*
	**  Make sure the read was OK
	*/
	if (rms_status == RMS$_EOF)
	    {
	    /*
	    **	Status is not good but it's a normal end of file
	    **	This also means that the source was an even multiple
	    **	of our buffer size.
	    */
	    end_of_file = TRUE;
	    break;
	    }
	else if (rms_status == RMS$_RER)
	    {
	    /*
	    **	This error usually means that we are reading a disk
	    **	as the source and we have reached the end of the disk.
	    **
	    **	There may be additional data to read if the disk size
	    **	is not an even multiple of the buffer size.  We will
	    **	read the last part of the disk one disk block at a time.
	    */
	    end_of_file = TRUE;
	    break;
	    }
	else
	    {
	    /*
	    **	It's not one of the expected errors, make sure it's ok
	    */
	    insure_ok(rms_status);

	    /*
	    **	If we got this far, the read was OK
	    **
	    **	Check the number of bytes read
	    **	It should always be the same as the buffer size
	    **	except for the last read.
	    */
	    if (srcrab.rab$w_rsz == buffer_size)
		{
		/*
		**  Just a normal read
		*/
		buffer_reads++;
/*  	printf("buffer_reads: %d\r",buffer_reads);  */
		brd = write(diskimage,&buf[0],buffer_size);
                        if(brd < 0) {
                                perror("write diskimage");
                                abort();
                        }
		}
	   }
	}

	/*
	**  Adjust buffer counters etc.
	*/

    rms_status = sys$close(&srcfab);
    insure_ok(rms_status);

    /*
    **	Print statistics
    */
    fprintf(stderr, "\n%d reads of %d bytes\n",
	buffer_reads,
	buffer_size);

}
