| #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);
}
|