/*
** COPYRIGHT (c) 1992, 1997, 1998 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.
*/

/*
**++
**  Facility:
**
**	Examples
**
**  Version: V1.3
**
**  Abstract:
**
**      GBLSEC.C -- global section example code
**
**	Creates a backing storage file, and maps a global section
**	into process virtual address space (twice), and then shows
**	basic section operations.
**
**  Author:
**	Stephen Hoffman
**
**  Creation Date:  2-Jan-1990
**
**  Modification History:
**
**	Stephen Hoffman	    remove unused "stubs"
**	V1.1 27-Aug-1997
**	Stephen Hoffman	    added sys$updsecw calls.
**	V1.2 07-Apr-1998
**	Stephen Hoffman	    added sys$updsecw calls.
**	V1.3 04-Feb-2000
**	Stephen Hoffman	    added explicit cleanup via $dassgn.
**
**  Build Instructions:
**
**      $ CC/DECC/PREFIX=ALL GBLSEC
**      $ LINK GBLSEC
**      $ RUN GBLSEC
**
**--
*/

#include <descrip.h>
#include <lib$routines.h>
#include <psldef.h>
#include <rms.h>
#include <secdef.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
#include <string.h>
#include <stsdef.h>

#define P0SPACE ((void*)0x0200)
#define GBLSECMAX 10

/*
//  Open the specified file, using basic RMS calls...
//  (The FAB$M_UFO is typically used with backing storage files.)
*/
RmsFileOpen( struct FAB *fab, char *FileName, char *DefFileName )
    {
    int RetStat;

    *fab = cc$rms_fab;

    fab->fab$l_alq = 10;
    fab->fab$b_fac = 0;
    fab->fab$l_fop = FAB$M_UFO | FAB$M_CIF;
    fab->fab$b_shr = FAB$M_UPI | FAB$M_SHRPUT | FAB$M_SHRGET | FAB$M_SHRUPD;

    fab->fab$l_fna = FileName;
    fab->fab$b_fns = strlen( FileName );
    fab->fab$l_dna = DefFileName;
    fab->fab$b_dns = strlen( DefFileName );

    /*
    //  Create or open the specified file -- it is created if
    //	not found, else it is opened.  (See the FAB$M_CIF bit.)
    */
    RetStat = sys$create( fab, 0, 0 );
    if ( !$VMS_STATUS_SUCCESS( RetStat ) )
	return RetStat;



    return RetStat;
    }

main()
    {
    int RetStat;
    $DESCRIPTOR( SecDsc, "FACNAM_GLOBAL_SECTION_NAME" );
    int i;
    unsigned short int Iosb[4];
    void *InAdr1[2] = {P0SPACE,P0SPACE};
    void *RetAdr1[2] = {NULL,NULL};
    void *InAdr2[2] = {P0SPACE,P0SPACE};
    void *RetAdr2[2] = {NULL,NULL};
    void *InAdr3[2] = {P0SPACE,P0SPACE};
    void *RetAdr3[2] = {NULL,NULL};
    struct FAB Fab1, Fab2, Fab3;
    struct SecStructDef
	{
	int Gblsec[GBLSECMAX];
	} *Sec1, *Sec2, *Sec3;

    /*
    //	Create and open, and then map the global section...
    //  Then overlay a structure onto the global section...
    */
    RetStat = RmsFileOpen( &Fab1, "GBLSEC", "SYS$SCRATCH:.TMP" );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    RetStat = sys$crmpsc( InAdr1, RetAdr1, PSL$C_USER, 
	SEC$M_EXPREG | SEC$M_WRT | SEC$M_DZRO | SEC$M_GBL,
	&SecDsc,
	0, 0, Fab1.fab$l_stv, 1, 0, 0, 0 );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    Sec1 = RetAdr1[0];

    /*
    //	Create and open, and then map the global section.  Again.
    //  Then overlay a structure onto the global section...
    */
    RetStat = RmsFileOpen( &Fab2, "GBLSEC", "SYS$SCRATCH:.TMP" );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    RetStat = sys$crmpsc( InAdr2, RetAdr2, PSL$C_USER, 
	SEC$M_EXPREG | SEC$M_WRT | SEC$M_GBL,
	&SecDsc,
	0, 0, Fab2.fab$l_stv, 1, 0, 0, 0 );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    Sec2 = RetAdr2[0];

    /*
    //  Now write some data into one "window"...  And then read the
    //  data back in from the other "window".
    */
    for ( i = 0; i < GBLSECMAX; i++)
	Sec1->Gblsec[i] = i;
    printf( "Sec1->Gblsec is located at %p\n", RetAdr1[0] );
    Sec1 = RetAdr1[0];
    for ( i = 0; i < GBLSECMAX; i++)
	printf( "  Sec1->Gblsec[%d] = %d\n", i, Sec1->Gblsec[i] );
    printf( "Sec2->Gblsec is located at %p\n", RetAdr2[0] );
    for ( i = 0; i < GBLSECMAX; i++)
	printf( "  Sec2->Gblsec[%d] = %d\n", i, Sec2->Gblsec[i] );


    /*
    //  Now flush out the contents of the section to disk...
    //  Twice.  Once for each of the two ranges mapped in...
    */
    RetStat = sys$updsecw( RetAdr1, NULL, PSL$C_USER, 0,
        0, Iosb, NULL, NULL );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    if (!$VMS_STATUS_SUCCESS( Iosb[0] ))
	lib$signal( Iosb[0] );

    RetStat = sys$updsecw( RetAdr2, NULL, PSL$C_USER, 0,
        0, Iosb, NULL, NULL );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    if (!$VMS_STATUS_SUCCESS( Iosb[0] ))
	lib$signal( Iosb[0] );

    /*
    // Now delete the section virtual address space range...
    */
    RetStat = sys$deltva( RetAdr1, NULL, PSL$C_USER );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    RetStat = sys$deltva( RetAdr2, NULL, PSL$C_USER );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );

    /*
    //  Now remap the second section, into the next available
    //  address space.  (This may well be in one of the same
    //  virtual address ranges we just deleted.)
    */
    RetStat = RmsFileOpen( &Fab3, "GBLSEC", "SYS$SCRATCH:.TMP" );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    RetStat = sys$crmpsc( InAdr3, RetAdr3, PSL$C_USER, 
	SEC$M_EXPREG | SEC$M_WRT | SEC$M_GBL,
	&SecDsc,
	0, 0, Fab3.fab$l_stv, 1, 0, 0, 0 );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    Sec3 = RetAdr3[0];

    /*
    //  And redisplay the contents of the section, as was
    //  maintained by the backing storage file...
    */
    printf( "Sec3->Gblsec is located at %p\n", RetAdr3[0] );
    for ( i = 0; i < GBLSECMAX; i++)
	printf( "  Sec3->Gblsec[%d] = %d\n", i, Sec3->Gblsec[i] );

    /*
    //  Close the channels to the file.  Since we used the UFO option,
    //  we cannot and do not use sys$close, we must use sys$dassgn...
    */
    RetStat = sys$dassgn( Fab1.fab$l_stv );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    RetStat = sys$dassgn( Fab2.fab$l_stv );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );
    RetStat = sys$dassgn( Fab3.fab$l_stv );
    if (!$VMS_STATUS_SUCCESS( RetStat ))
	lib$signal( RetStat );

    return SS$_NORMAL;
    }

