|  | #include	descrip
#include	lnmdef
#include	rms
#include	secdef
#include	string
#include	stsdef
#include	ssdef
/*
 * Manifest constants
 */
#define	TRUE	1
#define	FALSE	0
#define	NULL	((void*) 0)
/*
 * Local routines
 */
static	char	block_file(struct dsc$descriptor_s*);
static	char	compare(int,char*,char*);
static	char	extract_filename(struct dsc$descriptor_s*,char*);
static	char	find_string(int,int*,char*);
static	char	get_char(int,char*);
static	char	get_char_init(struct dsc$descriptor_s*);
static	char	get_char_quit(void);
static	char	map_file(struct dsc$descriptor_s*);
static	char	set_memory(char*,int,int);
static	char	test_previous(char*,char*,int*,int*);
/*
 * External functions
 */
extern	long	LIB$analyze_sdesc(struct dsc$descriptor_s*,short*,char**);
extern	long	STR$copy_r(struct dsc$descriptor_s*,short*,char*);
extern	long	SYS$close(struct FAB*,long(*),long(*));
extern	long	SYS$connect(struct RAB*,long(*),long(*));
extern	long	SYS$crelnm(long*,struct dsc$descriptor_s*,
			struct dsc$descriptor_s*,char*,void*);
extern	long	SYS$crmpsc(long*,long*,long,long,struct dsc$descriptor_s*,
			long*,long,short,long,long,long,long);
extern	long	SYS$dassgn(short);
extern	long	SYS$deltva(long*,long*,long);
extern	long	SYS$disconnect(struct RAB*,long(*),long(*));
extern	long	SYS$open(struct FAB*,long(*),long(*));
extern	long	SYS$parse(struct FAB*,long(*),long(*));
extern	long	SYS$read(struct RAB*,long(*),long(*));
extern	long	SYS$search(struct FAB*,long(*),long(*));
extern	long	SYS$trnlnm(long*,struct dsc$descriptor_s*,
			struct dsc$descriptor_s*,char*,void*);
/*
 * Local data
 */
static	char	end_stringA[]    = "/HEY TOM THERE IT WAS";
static	char	start_stringA[] = "HEY TOM HERE IT IS/";
static	char	logical_name_baseA[] = "UUCP_MAILSHR_%s_VERSION_DATA";
static	$DESCRIPTOR(system_table,"LNM$SYSTEM_TABLE");
static	long	filelength = 0;
static	char	mapped_file;
static	char	*dataP;
static	long	rangeA[2];
static	long	channel;
static	struct FAB	gfab;
static	struct RAB	grab;
static	char	bufferA[4096];
static	long	buflow;
static	long	bufhigh;
char get_version_string(
	struct dsc$descriptor_s	*filespecP,
	struct dsc$descriptor_s	*versionP)
{
	int	end;
	char	filenameA[NAM$C_MAXRSS+1];
	char	found = FALSE;
	int	i;
	char	gcinited = FALSE;
	char	ok = FALSE;
	char	remember = FALSE;
	int	start;
	short	tl;
	char	*tP;
	char	versionA[100];
/*
 * Setup to return an empty string if something goes amiss
 */
versionA[0] = '\0';
/*
 * Initialize the get_character routine. This takes care of opening the
 * file, mapping it into memory, whatever.
 */
if (!get_char_init(filespecP))
	goto ABORT;
gcinited = TRUE;
/*
 * Crack the filename out of the filespec
 */
if (!extract_filename(filespecP,filenameA))
	goto ABORT;
/*
 * See if we have previously looked up the string
 */
if (!test_previous(filenameA,&found,&start,&end))
	goto ABORT;
/*
 * If we have not previously found it, we need to go look for it
 */
if (!found)
	{
	/*
	 * Find the start pattern
	 */
	if (!find_string(0,&start,start_stringA))
		goto ABORT;
	/*
	 * Continue processing if we found it
	 */
	if (start >= 0)
		{
		/*
		 * Find the end pattern
		 */
		start += strlen(start_stringA);
		if (!find_string(start,&end,end_stringA))
			goto ABORT;
		/*
		 * Continue processing if we found it
		 */
		if (end >= start)
			{
			found = TRUE;
			remember = TRUE;
			}
		}
	}
/*
 * The version string is sandwiched between the start and end patterns. Copy
 * it out.
 */
if (found)
	{
	tP = versionA;
	for (i=start;i<end;i++)
		if (!get_char(i,tP++))
			goto ABORT;
	*tP = '\0';
	}
/*
 * Remember where we found the pattern so that we don't have to go hunting
 * all over the file for it next time.
 */
if (remember)
	if (!set_memory(filenameA,start,end))
		goto ABORT;
ok = TRUE;
ABORT:
/*
 * Return the string
 */
tl = strlen(versionA);
STR$copy_r(versionP,&tl,versionA);
/*
 * Clean up
 */
if (gcinited)
	get_char_quit();
return(ok);
}
static char block_file(
	struct dsc$descriptor_s *filespecP)
{
	char	ok = FALSE;
	short	tl;
/*
 * Perform an RMS block mode open on the file
 */
gfab = cc$rms_fab;
LIB$analyze_sdesc(filespecP,&tl,&gfab.fab$l_fna);
gfab.fab$b_fns = tl;
gfab.fab$b_fac = FAB$M_BIO | FAB$M_GET;
gfab.fab$b_shr = FAB$M_SHRGET;
if (!$VMS_STATUS_SUCCESS(SYS$open(&gfab,NULL,NULL)))
	goto ABORT;
/*
 * Connect a record stream
 */
grab = cc$rms_rab;
grab.rab$l_fab = &gfab;
grab.rab$l_ubf = bufferA;
grab.rab$w_usz = sizeof(bufferA);
if (!$VMS_STATUS_SUCCESS(SYS$connect(&grab,NULL,NULL)))
	goto ABORT;
/*
 * Read a chunk of the file to init the buffer
 */
grab.rab$l_bkt = 0;
if (!$VMS_STATUS_SUCCESS(SYS$read(&grab,NULL,NULL)))
	goto ABORT;
/*
 * Set the upper limit based on the number of bytes
 * transferred.
 */
buflow = 0;
bufhigh = buflow + grab.rab$w_rsz - 1;
mapped_file = FALSE;
ok = TRUE;
ABORT:
return(ok);
}
static char compare(
	int	offset,
	char	*stringP,
	char	*foundP)
{
	char	c;
	char	ok = FALSE;
/*
 * Assume that we will find it
 */
*foundP = TRUE;
/*
 * Loop testing characters while we match or we run out
 */
while ((*stringP != '\0') && (*foundP))
	{
	/*
	 * Get a character from the file
	 */
	if (!get_char(offset++,&c))
		goto ABORT;
	/*
	 * Test the character
	 */
	*foundP = (c == *stringP++);
	}
ok = TRUE;
ABORT:
return(ok);
}
static char extract_filename(
	struct dsc$descriptor_s	*filespecP,
	char			*filenameP)
{
	char		esa[NAM$C_MAXRSS+1];
	struct FAB	fab;
	struct NAM	nam;
	char		ok = FALSE;
	char		rsa[NAM$C_MAXRSS+1];
	short		tl;
/*
 * Set up RMS control blocks
 */
fab = cc$rms_fab;
LIB$analyze_sdesc(filespecP,&tl,&fab.fab$l_fna);
fab.fab$b_fns = tl;
fab.fab$l_nam = &nam;
nam = cc$rms_nam;
nam.nam$l_esa = esa;
nam.nam$b_ess = NAM$C_MAXRSS;
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
/*
 * Call upon RMS to check the file spec and lookup the file
 */
if (!$VMS_STATUS_SUCCESS(SYS$parse(&fab,NULL,NULL)))
	goto ABORT;
if (!$VMS_STATUS_SUCCESS(SYS$search(&fab,NULL,NULL)))
	goto ABORT;
/*
 * The resultant string area now contains the complete filespec for the
 * file,
 */
memcpy(filenameP,nam.nam$l_name,nam.nam$b_name);
filenameP[nam.nam$b_name] = '\0';
ok = TRUE;
ABORT:
return(ok);
}
static char find_string(
	int	start,
	int	*positionP,
	char	*stringP)
{
	char	c;
	int	i;
	char	ok = FALSE;
	char	*tP;
tP = stringP;
i = 0;
/* 
 * Search the file until we reach the end of the string
 */
while (*tP != '\0')
	{
	/*
	 * Get the next character from the file. End of fail will take the
	 * abort.
	 */
	if (!get_char(start+i,&c))
		goto ABORT;
	/*
	 * Test against the next string character to be processed
	 */
	if (c == *tP)
		{
		/*
		 * Match, go to the next character
		 */
		i++;
		tP++;
		}
	 else
		{
		/*
		 * No match, reanchor the search and start over
		 */
		start++;
		i = 0;
		tP = stringP;
		}
	}
/*
 * If we are here, we found the end of the string!
 */
*positionP = start;
ok = TRUE;
ABORT:
return(ok);
}
static char get_char(
	int	charnum,
	char	*cP)
{
	char		ok = FALSE;
/*
 * Which method are we using for dealing with the file?
 */
if (mapped_file)
	{
	/*
	 * This is easy.
	 */
	if ((charnum >= 0) && (charnum < filelength))
		*cP = dataP[charnum];
	 else
		/*
		 * Out of range!
		 */
		goto ABORT;	
	}
 else
	{
	/*
	 * Is the requested byte in the buffer?
	 */
	if ((charnum >= buflow) && (charnum <= bufhigh))
		*cP = bufferA[charnum - buflow];
	 else if ((charnum >= 0) && (charnum < filelength))
		{
		/*
		 * Requested byte is not in the buffer but it is in the file.
		 * Reload the buffer to a point that is one disk block prior
		 * to the requested byte.
		 */
		buflow = (charnum & ~511) - 512;
		if (buflow < 0)
			buflow = 0;
		/*
		 * Read from the file
		 */
		grab.rab$l_bkt = buflow / 512;
		if (!$VMS_STATUS_SUCCESS(SYS$read(&grab,NULL,NULL)))
			goto ABORT;
		/*
		 * Set the upper limit based on the number of bytes
		 * transferred.
		 */
		bufhigh = buflow + grab.rab$w_rsz - 1;
		/*
		 * Now return the character
		 */
		*cP = bufferA[charnum - buflow];
		}
	 else
		/*
		 * Out of range!
		 */
		goto ABORT;
	}
ok = TRUE;
ABORT:
return(ok);
}
static char get_char_init(
	struct dsc$descriptor_s	*filespecP)
{
	struct FAB	fab;
	char	ok = FALSE;
	short	tl;
	struct XABFHC	xabfhc;
/*
 * Make sure that some defaults get loaded into things so that closedown
 * work properly
 */
channel = -1;
rangeA[0] = -1;
gfab = cc$rms_fab;
grab = cc$rms_rab;
/*
 * Lookup the file so we know how long it is.
 */
fab = cc$rms_fab;
LIB$analyze_sdesc(filespecP,&tl,&fab.fab$l_fna);
fab.fab$b_fns = tl;
fab.fab$l_xab = &xabfhc;
xabfhc = cc$rms_xabfhc;
if (!$VMS_STATUS_SUCCESS(SYS$open(&fab,NULL,NULL)))
	goto ABORT;
if (!$VMS_STATUS_SUCCESS(SYS$close(&fab,NULL,NULL)))
	goto ABORT;
filelength = (xabfhc.xab$l_ebk-1) * 512 + xabfhc.xab$w_ffb;
/*
 * Attempt to map the file into memory. That will be the most efficient
 * way of dealing with it
 */
if (!map_file(filespecP))
	/*
	 * Ok, so that didn't work. How about RMS block mode?
	 */
	if (!block_file(filespecP))
		/*
		 * That doesn't want to work either? Oh well.
		 */
		goto ABORT;
ok = TRUE;
ABORT:
return(ok);
}
static char get_char_quit()
{
	char	ok = FALSE;
/*
 * Which way are we shutting down?
 */
if (mapped_file)
	{
	/*
	 * Release the section file and close it
	 */
	if (rangeA[0] != -1)
		SYS$deltva(rangeA,NULL,NULL);
	if (channel != -1)
		SYS$dassgn(channel);
	}
 else
	{
	/*
	 * Shut down RMS access to the file
	 */
	if (grab.rab$w_isi != 0)
		SYS$disconnect(&grab,NULL,NULL);
	if (gfab.fab$w_ifi != 0)
		SYS$close(&gfab,NULL,NULL);
	}
ok = TRUE;
ABORT:
return(ok);
}
static char map_file(
	struct dsc$descriptor_s *filespecP)
{
	long	inadrA[2];
	char	ok = FALSE;
	short	tl;
/*
 * Perform an RMS level user open on the file
 */
gfab = cc$rms_fab;
LIB$analyze_sdesc(filespecP,&tl,&gfab.fab$l_fna);
gfab.fab$b_fns = tl;
gfab.fab$l_fop = FAB$M_UFO;
if (!$VMS_STATUS_SUCCESS(SYS$open(&gfab,NULL,NULL)))
	goto ABORT;
channel = gfab.fab$l_stv;
/*
 * Map the file into a private section
 */
inadrA[0] = 0;
inadrA[1] = 0;
if (!$VMS_STATUS_SUCCESS(SYS$crmpsc(inadrA,rangeA,0,SEC$M_EXPREG,NULL,NULL,
							0,channel,0,0,0,0)))
	goto ABORT;
dataP = (char*) rangeA[0];
mapped_file = TRUE;
ok = TRUE;
ABORT:
return(ok);
}
static char set_memory(
	char	*filenameP,
	int	start,
	int	end)
{
	struct	{
		short int	buflen;
		short int	code;
		long		*bufadr;
		short int	*retlen;
		unsigned	terminator;
		} lnm_item_list;
	char	logical_nameA[100];
	struct dsc$descriptor_s	logical_name_desc;
	char	ok = FALSE;
	char	translationA[101];
/*
 * Take the filename and create a logical name
 */
sprintf(logical_nameA,logical_name_baseA,filenameP);
/*
 * Take the start and end values and make the value for the logical name
 */
sprintf(translationA,"!%d,%d",start,end);
/*
 * Setup for a create logical name service
 */
lnm_item_list.buflen     = strlen(translationA);
lnm_item_list.code       = LNM$_STRING;
lnm_item_list.bufadr     = translationA;
lnm_item_list.retlen     = NULL;
lnm_item_list.terminator = 0;
logical_name_desc.dsc$w_length  = strlen(logical_nameA);
logical_name_desc.dsc$b_dtype   = DSC$K_DTYPE_T;
logical_name_desc.dsc$b_class   = DSC$K_CLASS_S;
logical_name_desc.dsc$a_pointer = logical_nameA;
/*
 * Create the logical
 */
if (!$VMS_STATUS_SUCCESS(SYS$crelnm(NULL,&system_table,&logical_name_desc,0,
							&lnm_item_list)))
	goto ABORT;
ok = TRUE;
ABORT:
return(ok);
}
static char test_previous(
	char	*filenameP,
	char	*foundP,
	int	*startP,
	int	*endP)
{
	char	c;
	int	i;	
	struct	{
		short int	buflen;
		short int	code;
		long		*bufadr;
		short int	*retlen;
		unsigned	terminator;
		} lnm_item_list;
	char	logical_nameA[100];
	struct dsc$descriptor_s	logical_name_desc;
	char	ok = FALSE;
	long	status;
	char	translationA[101];
	short	translen;
	char	*tP;
/*
 * Assume that we will not find it
 */
*foundP = FALSE;
/*
 * Take the filename and create a logical name
 */
sprintf(logical_nameA,logical_name_baseA,filenameP);
/*
 * Setup for a translate logical name service
 */
lnm_item_list.buflen     = sizeof(translationA) - 1;
lnm_item_list.code       = LNM$_STRING;
lnm_item_list.bufadr     = translationA;
lnm_item_list.retlen     = &translen;
lnm_item_list.terminator = 0;
logical_name_desc.dsc$w_length  = strlen(logical_nameA);
logical_name_desc.dsc$b_dtype   = DSC$K_DTYPE_T;
logical_name_desc.dsc$b_class   = DSC$K_CLASS_S;
logical_name_desc.dsc$a_pointer = logical_nameA;
/*
 * Translate the logical
 */
status = SYS$trnlnm(NULL,&system_table,&logical_name_desc,0,&lnm_item_list);
/*
 * Dispatch based on the result
 */
switch (status)
 {
 case SS$_NORMAL:
	{
	/*
	 * Logical name is defined. Parse it.
	 */
	translationA[translen] = '\0';
	/*
	 * If the first character is not a "!", this logical was created
	 * by something other than this code.
	 */
	if (translationA[0] != '!')
		{
		*foundP = FALSE;
		goto PICKUP;
		}
	/*
	 * Get the start value
	 */
	tP = strtok(&translationA[1],",");
	if (tP == NULL)
		{
		*foundP = FALSE;
		goto PICKUP;
		}
	*startP = atoi(tP);
	/*
	 * Get the end value
	 */
	tP = strtok(NULL,",");
	if (tP == NULL)
		{
		*foundP = FALSE;
		goto PICKUP;
		}
	*endP = atoi(tP);
	/*
	 * Now, compare the strings found at the start and end positions
	 * with the strings we expect to find.
	 */
	if (!compare(*startP-strlen(start_stringA),start_stringA,foundP))
		{
		*foundP = FALSE;
		goto PICKUP;
		}
	if (*foundP)
		if (!compare(*endP,end_stringA,foundP))
			{
			*foundP = FALSE;
			goto PICKUP;
			}
PICKUP:
	break;
	}
 case SS$_NOLOGNAM:	/* No such name defined for this system */
	{
	*foundP = FALSE;
	break;
	}
 default:
	{
	goto ABORT;
	break;
	}
 }
ok = TRUE;
ABORT:
return(ok);
}
 | 
|  | /*
 * SPOOL_CHECK.C
 *
 * Given the path name to a file, verify that it exists, and that it is
 * located in UUCP_SPOOL or a subdirectory thereof.
 */
#include	descrip
#include	lnmdef
#include	psldef
#include	rms
#include	string
#include	stsdef
#define	TRUE	1
#define	FALSE	0
#define	NULL	((void*) 0)
	struct lnm_list	{
		short int	indlen;
		short int	indcode;
		long		*indadr;
		short int	*indret;
		short int	buflen;
		short int	bufcode;
		char		*bufadr;
		short int	*retlenadr;
		unsigned	terminator;
		};
	struct lnm_list_short {
		short int	indlen;
		short int	indcode;
		long		*indadr;
		short int	*indret;
		unsigned	terminator;
		};
extern	long	SYS$close(struct FAB*,long(*),long(*));
extern	long	SYS$open(struct FAB*,long(*),long(*));
extern	long	SYS$parse(struct FAB*,long(*),long(*));
extern	long	SYS$search(struct FAB*,long(*),long(*));
extern	long	SYS$trnlnm(long*,struct dsc$descriptor_s*,
			struct dsc$descriptor_s*,char*,struct lnm_list*);
extern	long	LIB$analyze_sdesc(struct dsc$descriptor_s*,short*,char**);
extern	long	STR$copy_r(struct dsc$descriptor_s*,short*,char*);
static	$DESCRIPTOR(logical_name,"UUCP_SPOOL");
static	$DESCRIPTOR(system_table,"LNM$SYSTEM_TABLE");
char spool_check(infilenameP,outfilenameP,mrsP)
	struct dsc$descriptor_s *infilenameP;
	struct dsc$descriptor_s *outfilenameP;
	int			*mrsP;
{
	char		dvi[NAM$C_DVI];
	char		esa[NAM$C_MAXRSS+1];
	struct FAB	fab;
	short		fid[3];
	char		ftv[NAM$C_MAXRSS+1];
	struct lnm_list	list;
	char		mode;
	int		max_index;
	struct NAM	nam;
	char		ok = FALSE;
	char		rsa[NAM$C_MAXRSS+1];
	char		scratch[NAM$C_MAXRSS+1];
	short		scratchlen;
	struct lnm_list_short short_list;
	long		status;
	int		t;
	int		translation;
/*
 * Use RMS calls to lookup the file. This has two effects: it tells
 * us that it is there and fetches the file id.
 */
fab = cc$rms_fab;
LIB$analyze_sdesc(infilenameP,&scratchlen,&fab.fab$l_fna);
fab.fab$b_fns = scratchlen;
fab.fab$l_nam = &nam;
nam = cc$rms_nam;
nam.nam$l_esa = esa;
nam.nam$b_ess = NAM$C_MAXRSS;
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
if (!$VMS_STATUS_SUCCESS(SYS$parse(&fab,NULL,NULL)))
	goto ABORT;
if (!$VMS_STATUS_SUCCESS(SYS$search(&fab,NULL,NULL)))
	goto ABORT;
/*
 * Preserve the device and file id's
 */
memcpy(dvi,nam.nam$t_dvi,sizeof(dvi));
memcpy(fid,nam.nam$w_fid,sizeof(fid));
/*
 * Preserve the file name, type and version in a C style string
 */
t = 0;
memcpy(&ftv[t],nam.nam$l_name,nam.nam$b_name);
t += nam.nam$b_name;
memcpy(&ftv[t],nam.nam$l_type,nam.nam$b_type);
t += nam.nam$b_type;
memcpy(&ftv[t],nam.nam$l_ver,nam.nam$b_ver);
t += nam.nam$b_ver;
ftv[t] = '\0';
/*
 * Translate UUCP_SPOOL to determine how many translations it has
 */
short_list.indlen     = sizeof(max_index);
short_list.indcode    = LNM$_MAX_INDEX;
short_list.indadr     = &max_index;
short_list.indret     = NULL;
short_list.terminator = 0;
mode = PSL$C_EXEC;
if (!$VMS_STATUS_SUCCESS(SYS$trnlnm(NULL,&system_table,&logical_name,
							&mode,&short_list)))
	goto ABORT;
if (max_index < 0)
	goto ABORT;
/*
 * Initialize for the loop below
 */
list.indlen     = sizeof(translation);
list.indcode    = LNM$_INDEX;
list.indadr     = &translation;
list.indret     = NULL;
list.buflen     = sizeof(scratch) - 1;
list.bufcode    = LNM$_STRING; 
list.bufadr     = scratch;
list.retlenadr  = &scratchlen;
list.terminator = 0;
mode = PSL$C_EXEC;
/*
 * Loop looking for the file in each directory referred to by UUCP_SPOOL:
 */
translation = 0;
do	{
	/*
 	 * Translate UUCP_SPOOL
	 */
	if (!$VMS_STATUS_SUCCESS(SYS$trnlnm(NULL,&system_table,&logical_name,
								&mode,&list)))
		goto ABORT;
	/*
	 * Parse it which will give us a real path
	 */
	fab.fab$l_fna = scratch;
	fab.fab$b_fns = scratchlen;
	if (!$VMS_STATUS_SUCCESS(SYS$parse(&fab,NULL,NULL)))
		goto ABORT;
	/*
	 * Copy the resulting expanded name up to the end of the directory
	 * specification to the scratch area
	 */
	t = &nam.nam$l_dir[nam.nam$b_dir] - esa;
	memcpy(scratch,esa,t);
	scratch[t] = '\0';
	/*
	 * Destroy the directory terminator, and make a wildcard
	 * search string for the file.
	 */
	if (scratch[t-1] == ']')
		strcpy(&scratch[t-1],"...]");
	 else
		strcpy(&scratch[t-1],"...>");
	strcat(scratch,ftv);
	/*
	 * Search for the file
	 */
	fab.fab$l_fna = scratch;
	fab.fab$b_fns = strlen(scratch);	
	
	if (!$VMS_STATUS_SUCCESS(SYS$parse(&fab,NULL,NULL)))
		goto ABORT;
	do	{
		status = SYS$search(&fab,NULL,NULL);
		/*
		 * If we found a file, check the resulting device
		 * and file id's for a match.
		 */
		if (($VMS_STATUS_SUCCESS(status)) &&
		    (memcmp(&dvi[1],&nam.nam$t_dvi[1],dvi[0]) == 0) &&
		    (memcmp(fid,nam.nam$w_fid,sizeof(fid)) == 0))
			{
			/*
			 * We win!
			 */
			scratchlen = nam.nam$b_esl;
			STR$copy_r(outfilenameP,&scratchlen,nam.nam$l_esa);
			/*
			 * Need to open and close the file to fill in the
			 * file attributes.
			 */
			fab.fab$l_fop = FAB$M_NAM;
			if (!$VMS_STATUS_SUCCESS(SYS$open(&fab,NULL,NULL)))
				goto ABORT;
			if (!$VMS_STATUS_SUCCESS(SYS$close(&fab,NULL,NULL)))
				goto ABORT;
			*mrsP = fab.fab$w_mrs;
			ok = TRUE;
			}
		} while ((!ok) && ($VMS_STATUS_SUCCESS(status)));
	/*
	 * Always increment the translation counter even though we might
	 * not go around again.
	 */		
	translation++;
	} while ((translation <= max_index) && (!ok));
ABORT:
return(ok);
}
 |