/*  .TITLE  FIXDRIVER - VAX/VMS Device Driver RENAME Program.		    */
/*  .IDENT  'X001-01'							    */
/*									    */
/*  BY:  William J. Sabatine - Micro Technology, Inc.  Anaheim, CA.	    */


#include    <rms>				    /* RMS routines	    */
#include    <iodef>				    /* I/O constants	    */
#include    <ssdef>				    /* Sys status constants */
#include    <libdef>				    /* Library constants    */
#include    <descrip>				    /* Descriptor macros    */
#include    <lib$routines>			    /* Library calls	    */


#define	BUFFER_SIZE	    255			    /* Image filespec size  */
#define NEW_NAME_SIZE       9			    /* New image name size  */
#define DISK_BLOCK_SIZE     512			    /* Size of disk blocks  */
#define PROLOG_TABLE_OFFSET 36			    /* Offset in image	    */


char	driver_buffer[BUFFER_SIZE];		    /* Image filespec buff  */
char	new_name_buffer[NEW_NAME_SIZE];		    /* New image name buff  */


$DESCRIPTOR(driver_buffer_desc, driver_buffer);	    /* Image file spec desc */
$DESCRIPTOR(new_name_buffer_desc, new_name_buffer); /* New image name desc  */


unsigned long	fixup_driver();			    /* Modifies image	    */


main()
{

/* main() performs the image open, read and write calls.		    */
/* It calls get_input() to receive filespecs from the user, and		    */
/* fixup_driver() to modify the image to the new name.			    */



/* Define user messages.						    */

$DESCRIPTOR(done_message, "Driver Fixup Successful");
$DESCRIPTOR(badimage_message, "New name or image is invalid - Fixup failed");


struct
{
   unsigned short   condition_value;	/* I/O status block - return status.*/
   unsigned short   transfer_count;	/* I/O status block - not used by us*/
   unsigned long    information;	/* I/O status block - not used by us*/
}  driver_iosb = {0, 0, 0};		/* Initialize before use with QIO   */


struct	FAB	driver_fab;		/* File Access Block for $OPEN	    */


unsigned long	 status;		/* Results indicator for sys calls  */
unsigned long	 image_size;		/* Size in bytes of driver image    */
char		*image_pointer;		/* Pointer to image in memory	    */



/* Call to get_input() to receive image name and new name from user.	    */

get_input();



/* Initialize the FAB with the system defaults.				    */
/* Add User File Open option, allow reads and writes and assign buffers.    */

driver_fab = cc$rms_fab;

driver_fab.fab$l_fop = FAB$M_UFO;
driver_fab.fab$b_fac = FAB$M_GET|FAB$M_PUT;
driver_fab.fab$l_fna = &driver_buffer;
driver_fab.fab$b_fns = driver_buffer_desc.dsc$w_length;



/* Perform the file open only.  No other RMS to do (via UFO).		    */

status = sys$open(&driver_fab);
if (status != RMS$_NORMAL) sys$exit(status);



/* Calculate image size as disk blocks used times block size.		    */
/* Allocate enough memory to read in entire image at once.		    */
/* Perform QIO to get the entire image.					    */

image_size = driver_fab.fab$l_alq * DISK_BLOCK_SIZE;

status = lib$get_vm(&image_size, &image_pointer, 0);
if (status != SS$_NORMAL) sys$exit(status);



status = sys$qiow(0, driver_fab.fab$l_stv,
		  IO$_READVBLK,
		  &driver_iosb, 0, 0,
		  image_pointer,
		  image_size, 1, 0, 0, 0);

if (status != SS$_NORMAL) sys$exit(status);

if (driver_iosb.condition_value != SS$_NORMAL)
    sys$exit(driver_iosb.condition_value);



/* Call fixup_driver() to modify the driver image to the new name.	    */
/* Call QIO to write out the image if all is ok.			    */
/* Write message for user indicating the problem or success.		    */
/* Close the I/O channel when through.					    */

status = fixup_driver(image_pointer, &new_name_buffer);



if (!status)
{
    status = sys$qiow(0, driver_fab.fab$l_stv,
   		      IO$_WRITEVBLK,
		      &driver_iosb, 0, 0,
		      image_pointer,
		      image_size, 1, 0, 0, 0);

    if (status != SS$_NORMAL) sys$exit(status);

    if (driver_iosb.condition_value != SS$_NORMAL)
	sys$exit(driver_iosb.condition_value);


    status = lib$put_output(&done_message);
    if (status != SS$_NORMAL) sys$exit(status);
}
else
{
    status = lib$put_output(&badimage_message);
    if (status != SS$_NORMAL) sys$exit(status);
}


status = sys$dassgn(driver_fab.fab$l_stv);
if (status != SS$_NORMAL) sys$exit(status);

}


get_input()
{

/* get_input() receives the image filespec and new image name from the user.*/


$DESCRIPTOR(name_prompt,"_New Name: ");		/* Prompt for new image name*/
$DESCRIPTOR(driver_prompt,"_Driver Name: ");	/* Prompt for image filespec*/


unsigned long	status;				/* Holds status of sys calls*/
unsigned long	flag = 1;			/* Lib$ flag for prompt.    */
char	 	*index;				/* Search ptr to input str. */


/* Check to command line for input and ask for image name if not provided.  */
/* Check for both image name AND new name in command line string.	    */

status = lib$get_foreign(&driver_buffer_desc,
                         &driver_prompt,
			 &driver_buffer_desc.dsc$w_length);

if (status != SS$_NORMAL) sys$exit(status);



driver_buffer[driver_buffer_desc.dsc$w_length] = '\0';
index = strchr(driver_buffer, ' ');


/* If the new name was not given in command line, ask for it.		    */
/* Otherwise, parse it out of the input filespec string and adjust lengths  */

if (!index)
{
    status = lib$get_foreign(&new_name_buffer_desc,
	                     &name_prompt,
			     &new_name_buffer_desc.dsc$w_length,
                             &flag);

    if ( (status != SS$_NORMAL) & (status != LIB$_INPSTRTRU) )
	sys$exit(status);
}


else
{
    strncpy(&new_name_buffer, index+1, 8);

    new_name_buffer_desc.dsc$w_length = 8;
    driver_buffer_desc.dsc$w_length = index - &driver_buffer;
}

}


unsigned long fixup_driver(driver_pointer, name_pointer)
char	*driver_pointer;
char	*name_pointer;

/* Fixup_driver() modified driver image to the new name specified.	    */
{


/* status = Holds return status from system calls.			    */
/* offset = Holds offset into driver image containing name to be modified.  */
/* syntax = Contains name to match against as a check before imge change.   */


unsigned long	status = 0;
unsigned long	offset = (DISK_BLOCK_SIZE + 1 + PROLOG_TABLE_OFFSET);

char		syntax[7] = "DRIVER";


/* Double check that we were given a legit name by the user.                */
/* Double check that we have a legit image name.                            */
/* If all ok, change the first two bytes to the new name.	            */

status = strncmp((name_pointer+2), syntax, 6);


if (!status)
{

    status = strncmp((driver_pointer+offset+2), syntax, 6);
    if (!status)
    {

	*(driver_pointer+offset+0) = *(name_pointer+0);
	*(driver_pointer+offset+1) = *(name_pointer+1);
    }

}

return (status);

}
