Article 163209 of comp.os.vms:
	As I understood right, in order to map a global section to a disk
	file, first, I need to open/create the file, and then to use the i/o
	channel of the file with the sys$crmpsc service.  Everything is fine,
	the problem is, how to I get a channel number from a simple fopen() or
	even open()?

You don't.  fopen() and open() are part of the C run-time library; they are
implemented on top of RMS, which is in turn implemented on top of the VMS file
access code.  While it's possible (non-trivially) to get to the channel number
by grubbing through control structures, it wouldn't do you any good anyway:
RMS will have opened the file in executive mode, and your user-mode code won't
be able to access it directly.

	Is there another way to do this? I saw a small macro32 code someone
	wrote in oursite on a vax-machine that returns a channel to a file,
	but I need to do that on an alpha. 

Again, it wouldn't do you any good.

Nominally, you need to access the file directly through the VMS file system
level (the ACP QIO calls).  This is a real pain to do, but fortunately it
isn't necessary:  You can get RMS to do the dirty work and then hand the file
over to you.  What you need to do is specify the UFO (User File Open) option
when you open the file in RMS.  This tells RMS that you intend to control the
file yourself.  It opens it in user mode, but then doesn't permit any further
use of it.

I've attached an excerpt from some code that does exactly what I've described.
It's a piece of a much bigger system, and it isn't worth it for me to track
down all the various include files needed even to describe all the datatypes
used, but it should give you the overall picture.
							-- Jerry

#include rms
#include secdef

static struct FAB fab;
static struct XABFHC xab;

/*
 * Map to a new section, creating it if necessary.  The actual creation must
 * take place under mutual exclusion, handled through the LOCK_NEWSECTION bit
 * in the common section.  This is necessary to avoid the following (unlikely,
 * but it actually occured during an early test) race condition:
 *
 *	Process A executes SYS$CREATE, creating a new file.
 *	Process B executes SYS$CREATE, finds the file already exists, hence
 *		does not set DZRO in flags.  It then executes SYS$CRMPSC.
 *	Process A DOES set DZRO, but by now the section exists, so this has
 *		no effect on its call to SYS$CRMPSC.
 *
 * At this point, whatever garbage was in the newly-created file is found in
 * the section.  In particular, the "ready" byte is probably set, but various
 * locks are not initialized, and everything falls apart.
 *
 */
COND
NewSection(base,name,pages,fspec)
SECTION **base;				/* Base address of section	*/
char name[];				/* (Base) name of section	*/
LONG pages;				/* Number of pages		*/
char fspec[];				/* Optional associated file;	*/
					/*  NULL for pagefile section	*/
{	COND status;
	ADDR_RANGE inadr = {0 , 0};	/* Input address range (P0)	*/
	ADDR_RANGE retadr;		/* Returned address range	*/
	LONG flags = SEC$M_GBL | SEC$M_EXPREG | SEC$M_WRT;
	struct match {
		LONG criteria;
		LONG version;
		} match;
	CHANNEL chan = 0;		/* Channel number		*/
	FILE_PROT prot = 0xFF0F;	/* Protection - OWNER only	*/

	if (strlen(name) > MAXSECTIONNAME)
		BUGCHECK("Section name is too long");

	match.criteria = SEC$K_MATALL;
	match.version = 0;

	if (Common != NULL)
		Spinlock(&Common->locks,CS$V_LOCK_NEWSECTION);
	if (nargs() < 4 || fspec == 0)
		flags |= SEC$M_DZRO | SEC$M_PAGFIL;
	else
	{	fab = cc$rms_fab;
		fab.fab$l_fna = fspec;
		fab.fab$b_fns = strlen(fspec);

		fab.fab$l_alq = pages;
		fab.fab$b_fac = FAB$M_GET | FAB$M_PUT;
		fab.fab$l_fop = FAB$M_CIF | FAB$M_UFO;
		fab.fab$w_mrs = 512;
		fab.fab$b_org = FAB$C_SEQ;
		fab.fab$b_rat = 0;
		fab.fab$b_rfm = FAB$C_FIX;
		fab.fab$b_rtv = 255;
		fab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_UPI;
		fab.fab$l_xab = &xab;

		xab = cc$rms_xabfhc;		/* File header XAB	*/
		xab.xab$l_nxt = 0;		/* (input only)		*/

		TEST(status = SYS$CREATE(&fab));
		chan = fab.fab$l_stv;
		if (status == RMS$_CREATED)	/* New file		*/
			flags |= SEC$M_DZRO;	/* Start with 0's	*/
		else	pages = xab.xab$l_ebk - 1;
			/* Get length.  The "- 1" is there because we	*/
			/* always allocate an even number of pages, so	*/
			/* FFB would be 0 and EBK is the NEXT block.	*/
	}

	TEST(status = SYS$CRMPSC(&inadr,	/* inadr	*/
			&retadr,		/* retadr	*/
			0,			/* acmode	*/
			flags,			/* flags	*/
			descr(PfxName(name)),	/* gsdname	*/
			&match,			/* ident	*/
			0,			/* relpage	*/
			chan,			/* chan		*/
			pages,			/* pagcnt	*/
			0,			/* vbn		*/
			prot,			/* protection	*/
			0));			/* pfc		*/

	*base = retadr.start;

	if (status == SS$_CREATED)		/* New section		*/
	{	(*base)->creator = ProcID;
		(*base)->chan = chan;
		(*base)->pages = pages;
		strcpy((*base)->name,name);
	}
	else					/* Old section		*/
	{	if (chan != 0)			/* File-based section	*/
			TEST(SYS$DASSGN(chan));	/* Don't need it	*/
	}

	return(status);
}


