/*-------------------------------------------------------------------+
| |
| S A S / C S A M P L E |
| Copyright (c) 1996, SAS Institute Inc. |
| Unpublished - All Rights Reserved |
| |
| NAME: LOADLIBS |
| LANGUAGE: C |
| PURPOSE: Demonstrates how to access members of a LOADLIB |
| and how to list a LOADLIBs contents. |
| This is done in two functions: |
| accessL() -- mimic the access() function for |
| CMS LOADLIBS. |
| LdLbList() -- list the contents of a CMS LOADLIB. |
| |
| INSTALLATION: |
| |
| COMPILE: LC370 LOADLIBS |
| LINK: CLINK caller LOADLIBS (GENMOD modulename |
| |
| Note: see EXAMPLE CALLS for sample programs to |
| exercise LOADLIBS functions. |
| |
| USAGE: |
| accessL PROTOTYPE CALL |
| rc = accessL(path, amode); |
| -ARG- -DCL--------- -DESCRIPTION- |
| path char * cms or tso style pathname (no cms: or|
| tso:) with or without member name. |
| amode int access mode: R_OK, W_OK, or 0 |
| rc int if 0, file found, otherwise not found|
| |
| LdLbList PROTOTYPE CALL |
| rc = LdLbList(fn); |
| -ARG- -DCL--------- -DESCRIPTION- |
| fn char * cms filename (ft of LOADLIB added) |
| rc int if 0, ok, otherwise, problem |
| |
| NOTES: This routine is intended for CMS only. |
| |
|--------------------------------------------------------------------|
| |
| EXAMPLE CALLS: |
| |
| 1) Example call using accessL function: |
| #include <stdio.h> |
| #include <fcntl.h> -- To get the R_OK and W_OK defines |
| #include "sampleh.h" |
| |
| int main(int argc, char **argv) |
| { |
| int rc, |
| amode=0; |
| char path[50]; |
| |
| if (argc < 3) |
| { |
| fprintf(stdout, "Usage: ACCESSLT fn member <mode>\n"); |
| return(-99); |
| } |
| |
| if (argv[3][0] == 'W') amode = W_OK; |
| else if (argv[3][0] == 'R') amode = R_OK; |
| else amode = 0; |
| |
| sprintf(path, "%s LOADLIB * (MEMBER %s", argv[1], argv[2]); |
| |
| rc = accessL(path, amode); |
| |
| fprintf(stdout,"member %s was %s in %s LOADLIB --rc=%d\n", |
| argv[2], (rc == 0 ? "FOUND" : "NOT FOUND"), argv[1], rc); |
| } |
| |
| 2) Example call using LdLbList function: |
| #include <stdio.h> |
| #include "sampleh.h" |
| |
| int main(int argc, char *argv[]) |
| { |
| int rc; |
| |
| if (argc < 2) |
| { |
| fprintf(stdout, "Usage: ListT fn \n"); |
| return(-99); |
| } |
| |
| rc = LdLbList(argv[1]); |
| return(rc); |
| } |
| MISC NOTES: |
| |
+-------------------------------------------------------------------*/
#pragma eject
#include <stdio.h> /* Needed for printf() etc. */
#include <cmsio.h> /* Needed for cmsopen, cmsread,etc*/
#include <string.h> /* Needed for strcpy, memcpy, etc.*/
#include <fcntl.h> /* Needed for W_OK & R_OK defines */
/*-------------------------------------------------------------------+
| Misc defines, etc... |
+-------------------------------------------------------------------*/
#define TRUE 1 /* True value */
#define FALSE 0 /* False value */
#define OK 0 /* Everything aok */
#define FAIL (-1) /* Problems, or member not found */
#define DO_ACCESS (-9) /* Failed - try access() */
#define ENTSZ 16 /* Dir entry size should be 16 */
#define ATTRSIZE 41 /* Size of attribute string */
#define ATTRITSZ 3 /* Size an attribute */
#define NUMATTRS 15 /* Number of attributes checked */
#define LINESIZE 80 /* Standard line size */
#define PATHSIZE 45 /* Size of a typical pathname */
#define NAMESIZE 8 /* Standard name size */
#define BIT0 128 /* 0x40 */
#define BIT1 64 /* 0x30 */
#define BIT2 32 /* 0x20 */
#define BIT3 16 /* 0x10 */
#define BIT4 8 /* 0x08 */
#define BIT5 4 /* 0x04 */
#define BIT6 2 /* 0x02 */
#define BIT7 1 /* 0x01 */
#define PDSLRMOD BIT3 /* RMODE Bit */
#define PDSAAMOD BIT4+BIT5 /* ALIAS EP AMODE Bits */
#define PDSMAMOD BIT6+BIT7 /* MAIN EP AMODE Bits */
/*-------------------------------------------------------------------+
| LOADLIB structures... |
+-------------------------------------------------------------------*/
typedef struct LHDR { /*--------------------------------*/
/* CMS LOADLIB header record. */
char ident[6]; /* Identifier = "LIBPDS" */
char RESERVED[2]; /* Reserved. */
int dirsz; /* Total directory size in bytes. */
int dir; /* Record number where Dir starts */
} LHDR; /*--------------------------------*/
typedef struct LDIR { /*--------------------------------*/
/* LOADLIB directory entry. */
/* NOTE: This struct was derived */
/* from the IHAPDS member */
/* of the SYS1.AMODGEN */
/* dataset on MVS/ESA. */
char name[NAMESIZE]; /* Member name. */
char _U1[2]; /* Unused. */
char flg1; /* Flag byte 1. */
char indc; /* Alias Indicator Byte (flag 2) */
char ttr[4]; /* Starting item no. of member. */
char ttrt[3]; /* TTR of 1st block of text. */
char zero; /* zero. */
char ttrn[3]; /* TTR of note list. */
char nl; /* Number of entries in note list.*/
char atr[2]; /* Member attributes. */
char stor[3]; /* Storage used. */
char ftbl[2]; /* Length of 1st block of text. */
char epa[3]; /* Entry point address. */
char ftbo[3]; /* PDS2FTBO. ftbo[1] contains the */
/* RMODE/AMODE bits. */
char _U2; /* Unused. */
char ssi[2]; /* SSI. */
char alias[NAMESIZE]; /* Alias name, if present. */
} LDIR; /*--------------------------------*/
/*-------------------------------------------------------------------+
| Misc. structures... |
+-------------------------------------------------------------------*/
typedef struct CMSFILE { /*--------------------------------*/
/* CMS LOW Level I/O cntl blks */
struct CMSFSCB fscb; /* CMS FSCB structure */
struct CMSFST fst; /* CMS FST structure */
} CMSFILE; /*--------------------------------*/
typedef struct LIBNAME { /*--------------------------------*/
/* LOADLIB filename structure. */
char path[PATHSIZE]; /* Path given by caller (stripped)*/
union { /* Union of 2 sets of ptrs... */
char *a[4]; /* Array of pointers to path. */
struct { /* Struct of pointers to path. */
char *fn; /* ptr to the filename */
char *ft; /* ptr to the filetype */
char *fm; /* ptr to the filemode */
char *memname; /* ptr to the member name. */
} s; /* */
} ptr; /* */
} LIBNAME; /*--------------------------------*/
typedef struct STATS { /*--------------------------------*/
/* Loadlib statistics struct */
int totsize; /* total size of loadlib */
int totmem; /* total number of members */
int totalias; /* total number of aliases */
} STATS; /*--------------------------------*/
/*-------------------------------------------------------------------+
| static functions called ... |
+-------------------------------------------------------------------*/
static int SrchLdLb( /* -- Search LdLb for name -- */
char * name, /* ptr to mem name to search for */
int dirsiz, /* size of the directory record */
char *direc /* ptr to the directory record */
);
static void ListDirR( /* -- List LdLb directory -- */
char *direc, /* ptr to the directory record */
int dirsiz, /* size of the directory record */
STATS *stats /* Loadlib statistics. */
);
static void GetAttrs( /* -- Get member attributes -- */
char *attrs, /* attribute string to build */
char *atr, /* attribute bits */
char *ftbo, /* amode/rmode bits */
int alias_flg /* is this an alias of a member? */
);
static int ParsePath( /* -- Parse a path into LIBNAME --*/
char *path, /* pathname */
LIBNAME *LibN /* ptr to LIBNAME struct to build */
);
static void AddFT( /* -- Build LIBNAME from a fn -- */
char *fn, /* LOADLIB fn */
LIBNAME *LibN /* ptr to LIBNAME struct to build */
);
static int InitLdLb( /* -- Init LdLb for reading dir --*/
LIBNAME *LLibName, /* CMS LOADLIB fn ft fm(no member)*/
CMSFILE **fptr, /* Ptr to CMSFILE struct. */
char **DirRec /* CMSREAD buffer */
);
/*-------------------------------------------------------------------+
| Macros... |
+-------------------------------------------------------------------*/
#define CLEANUP(retc) /* Return clean from accessL(). */\
{ if (fptr) /* */\
cmsclose(&(fptr->fscb));/* close the loadlib */\
if(DirRec) free(DirRec); /* free the read buffer */\
if(fptr) free(fptr); /* free the fscb & fst */\
return(retc); } /* return with a ret code. */
#pragma eject
/*-------------------------------------------------------------------+
| ENTRY: accessL |
| PURPOSE: Determine if a LOADLIB or LOADLIB member exists. |
| USAGE: _ PROTOTYPE CALL |
| rc = accessl(path, amode) |
| -ARG- -DCL--------- -DESCRIPTION- |
| path char * cms or tso style pathname (no cms: or|
| tso:) with or without member name. |
| amode int access mode: R_OK, W_OK, or 0 |
| rc int if 0, file found, otherwise not found|
| AREAS: CMSFILE(CMSFSCB, CMSFST), LHDR, LDIR, LIBNAME |
| EXTREF: access, cmsread |
| STATIC: ParsePath, InitLdLb, SrchLdLb, CLEANUP |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
int accessL(
char *path,
int amode
)
{
int found=FALSE, /* Member found? */
rc; /* Return code */
CMSFILE *fptr=NULL; /* CMSFILE ptr to FSCB & FST */
LIBNAME LibN; /* path name --> fn ft fm(MEM memb*/
char *DirRec=NULL; /* read buffer for Dir Record */
/*----------------------------------------------------------------+
| Parse the pathname. If no member found, call access & return. |
+----------------------------------------------------------------*/
if ((rc = ParsePath(path, &LibN)) != 0)
{
if (rc == DO_ACCESS) /* No member found, call access()*/
{
access(path, amode);
}
CLEANUP(rc);
}
/*----------------------------------------------------------------+
| Open the loadlib, read the header record, move file ptr to 1st |
| directory record. |
+----------------------------------------------------------------*/
if ((rc = InitLdLb(&LibN, &fptr, &DirRec)) != 0)
{
CLEANUP(rc);
}
/*----------------------------------------------------------------+
| If Write access requested, make sure the lib is on a Write disk |
| - first make sure the file is not on a readonly extension. |
| Then make sure it is on a write disk. |
+----------------------------------------------------------------*/
if ((amode & W_OK) == W_OK)
{
if((fptr->fst.flags & FSTXRDSK) == FSTXRDSK) /* R/O Ext bit? */
{
CLEANUP(FAIL);
}
else
{
if((fptr->fst.flags & FSTRWDSK) != FSTRWDSK) /* Write bit? */
{
CLEANUP(FAIL);
}
}
}
/*----------------------------------------------------------------+
| Read each dir entry, if member found quit, otherwise search |
| until found or last dir entry read. |
+----------------------------------------------------------------*/
found = FALSE; /* Start out right. */
while ( (cmsread(&(fptr->fscb)) == 0) &&
(fptr->fscb.aitn <= fptr->fst.aic) &&
!found)
{
/* Search dir entry rec for member*/
found = !(SrchLdLb(LibN.ptr.s.memname,fptr->fscb.nord, DirRec));
fptr->fscb.aitn++; /* Goto the next dir record. */
}
/*----------------------------------------------------------------+
| Clean Up and return whether we found the member or not. |
+----------------------------------------------------------------*/
CLEANUP(found == TRUE ? OK : FAIL);
}
#pragma eject
/*-------------------------------------------------------------------+
| ENTRY: LdLbList |
| PURPOSE: List the contents of a loadlib with attributes for |
| each member. |
| USAGE: _ PROTOTYPE CALL |
| rc = LdLbList(fn); |
| -ARG- -DCL--------- -DESCRIPTION- |
| fn char * cms filename (ft of LOADLIB added) |
| rc int if 0, ok, otherwise, problem |
| AREAS: CMSFILE(CMSFSCB, CMSFST), LHDR, LDIR, LIBNAME |
| EXTREF: cmsread, fprintf |
| STATIC: AddFT, InitLdLb, ListDirR, CLEANUP |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
int LdLbList(
char *fn
)
{
CMSFILE *fptr=NULL; /* CMSFILE ptr to FSCB & FST */
int rc=0; /* Return code */
LIBNAME LLibName; /* path name --> fn ft fm */
char *DirRec=NULL; /* read buffer for Dir Record */
STATS stats = {0,0,0}; /* Loadlib statistics structure */
/*----------------------------------------------------------------+
| Add a filetype of LOADLIB to the filename given. |
+----------------------------------------------------------------*/
AddFT(fn, &LLibName);
/*----------------------------------------------------------------+
| Open the loadlib, read the header record, move file ptr to 1st |
| directory record. |
+----------------------------------------------------------------*/
if ((rc = InitLdLb(&LLibName, &fptr, &DirRec)) != 0)
{
CLEANUP(rc);
}
/*----------------------------------------------------------------+
| Print the headings to stdout |
+----------------------------------------------------------------*/
fprintf(stdout, "%-8s %-6s %-6s %-6s %-8s %-41s \n",
"NAME", "TTR", "ENTRY", "STOR",
"ALIAS-TO", "-------------- ATTRIBUTES ---------------");
/*----------------------------------------------------------------+
| Read each line of directory, printing its contents |
+----------------------------------------------------------------*/
while ( (cmsread(&(fptr->fscb)) == 0) &&
(fptr->fscb.aitn <= fptr->fst.aic) )
{
/* List the members in this record*/
ListDirR(DirRec, fptr->fscb.nord, &stats);
fptr->fscb.aitn++; /* Goto the next dir record. */
}
/*----------------------------------------------------------------+
| Print Stats |
+----------------------------------------------------------------*/
fprintf(stdout, "\n\n"); /* Blank lines */
/* Total size */
if ((stats.totsize / 1024) > 1024)
{
fprintf(stdout, "Total Size = %6.2fM\n",
((float) stats.totsize/(1024*1024)) );
}
else
{
fprintf(stdout, "Total size = %6.2fK\n",
((float) stats.totsize/(1024)) );
}
/* Total members */
fprintf(stdout, "%d members \n", stats.totmem);
/* Average Module size */
fprintf(stdout, "Average member size = %6.2fK\n",
(((float) stats.totsize / (float) stats.totmem) / (1024)) );
/* Total Number of Aliases */
fprintf(stdout, "Total number of aliases = %d\n\n", stats.totalias);
/*----------------------------------------------------------------+
| Clean Up and return. |
+----------------------------------------------------------------*/
CLEANUP(OK);
}
#pragma eject
/*-------------------------------------------------------------------+
| FUNCTION: SrchLdLb |
| PURPOSE: Search a loadlib directory entry for a member. |
| AREAS: LDIR |
| EXTREF: strncmp |
| STATIC: - |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
static int SrchLdLb(
char *name, /* ptr to mem name to search for */
int dirsiz, /* size of the directory record */
char *direc) /* ptr to the directory record */
{
int i, /* Counter */
found = FALSE; /* Member found? */
LDIR *dirent; /* Loadlib Dir entry */
i = 0; /* Start out right */
while ((i < dirsiz) && !found) /* Search until found or done */
{
/*-------------------------------------------------------------+
| If the dir entry NULL, continue to next. |
+-------------------------------------------------------------*/
if (direc[i] == '\0')
{
i += 48;
continue;
}
/*-------------------------------------------------------------+
| Map the dir record to an LDIR |
+-------------------------------------------------------------*/
dirent = (LDIR *) (direc + i);
/*-------------------------------------------------------------+
| Do we match? |
+-------------------------------------------------------------*/
if (!strncmp(name, dirent->name,strlen(name)))
found = TRUE;
/*-------------------------------------------------------------+
| Go to the next entry. - check for an alias. |
+-------------------------------------------------------------*/
i += (48 + (((dirent->indc & 0x80) / 128) * ENTSZ));
}
return(found == TRUE ? OK : FAIL);
}
#pragma eject
/*-------------------------------------------------------------------+
| FUNCTION: ListDirR |
| PURPOSE: List all of the directory entries in a LOADLIB |
| directory record. |
| AREAS: LDIR |
| EXTREF: memcpy, fprintf, malloc |
| STATIC: GetAttrs |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
static void ListDirR(
char *direc, /* ptr to the directory record */
int dirsiz, /* size of the directory record */
STATS *stats) /* Loadlib statistics. */
{
int i, /* Counter */
alias_flag, /* Is this member an ALIAS? */
*ttr, /* TTR in a full Int */
*epa, /* EPA in a full Int */
*stor; /* STOR in a full Int */
char alias[NAMESIZE+1] = "\0", /* ALIAS Parent name */
/* Attribute string */
attrs[5*(LINESIZE+1)] = "\0";
LDIR *dirent; /* Loadlib Dir entry */
/*----------------------------------------------------------------+
| Get some space for the integer pointers |
+----------------------------------------------------------------*/
ttr = (int *) malloc(sizeof(int *));
epa = (int *) malloc(sizeof(int *));
stor = (int *) malloc(sizeof(int *));
i = 0; /* Start out right */
while (i < dirsiz)
{
/*-------------------------------------------------------------+
| If the dir entry NULL, continue to next. |
+-------------------------------------------------------------*/
if (direc[i] == '\0')
{
i += 48;
continue;
}
/*-------------------------------------------------------------+
| Map dir record to an LDIR |
+-------------------------------------------------------------*/
dirent = (struct LDIR *) (direc + i);
/*-------------------------------------------------------------+
| Process this Dir entry |
+-------------------------------------------------------------*/
/* Is this member an ALIAS? */
alias_flag = ((dirent->indc & 0x80) / 128);
if (alias_flag)
{
*stor = 0; /* 0 storage for alias members */
memcpy(alias, dirent->alias, NAMESIZE);
alias[8] = '\0';
stats->totalias++;
}
else
{
memcpy(stor, dirent->stor, 3);
*stor = *stor >> 8; /* Convert to Int */
/* Not an alias, so blank out name*/
memcpy(alias, " ", 8);
alias[8] = '\0';
stats->totsize += *stor;
}
stats->totmem++; /* Total members includes alias's */
/* Convert data to an int. */
memcpy(ttr, dirent->ttr, 4);
memcpy(epa, dirent->epa, 3);
*epa = *epa >> 8;
/*-------------------------------------------------------------+
| Get this member's attributes |
+-------------------------------------------------------------*/
GetAttrs(attrs, dirent->atr, dirent->ftbo, alias_flag);
/*-------------------------------------------------------------+
| Print the info |
+-------------------------------------------------------------*/
fprintf(stdout, "%8s %06X %06X %06X %8s %s\n",
dirent->name, *ttr, *epa, *stor, alias, attrs);
/*-------------------------------------------------------------+
| Go to the next entry. - check for an alias. |
+-------------------------------------------------------------*/
i += (48 + (alias_flag * ENTSZ));
}
}
#pragma eject
/*-------------------------------------------------------------------+
| FUNCTION: GetAttrs |
| PURPOSE: Get the attributes for a member in the loadlib |
| AREAS: parts of LDIR |
| EXTREF: memset, strcpy, strcat, strlen, sizeof |
| STATIC: - |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
static void GetAttrs(
char *attrs, /* attribute string to build */
char *atr, /* attribute bits */
char *ftbo, /* amode/rmode bits */
int alias_flg /* is this an alias of a member? */
)
{
struct ATab { /* Attribute table */
int Num; /* Attrubute byte number */
int And; /* Value to And Attrib byte with */
int Cmp; /* Value to compare anded val with*/
char *txt[2]; /* Text to print out for attribute*/
} ATab[NUMATTRS] = {
{/*0 RENT */ 0, 0x80, 0x80, {{"RN "}, {"NR "}} },
{/*1 REUS */ 0, 0x40, 0x40, {{"RU "}, {"NU "}} },
{/*2 Executable */ 0, 0x02, 0x02, {{"EX "}, {"NX "}} },
{/*3 OVERLAY */ 0, 0x20, 0x20, {{"OV "}, {""}} },
{/*4 TEST */ 0, 0x10, 0x10, {{"TE "}, {""}} },
{/*5 Only loadable */ 0, 0x08, 0x08, {{"OL "}, {""}} },
{/*6 Scatter format */ 0, 0x04, 0x04, {{"SF "}, {""}} },
{/*7 FLVL */ 1, 0x80, 0x80, {{"FV "}, {""}} },
{/*8 Origin 0 */ 1, 0x40, 0x40, {{"O0 "}, {""}} },
{/*9 Entry 0 */ 1, 0x20, 0x20, {{"E0 "}, {""}} },
{/*10 NRLD */ 1, 0x10, 0x10, {{"NL "}, {""}} },
{/*11 NREP */ 1, 0x08, 0x08, {{"NP "}, {""}} },
{/*12 TESTRAN */ 1, 0x04, 0x04, {{"TR "}, {""}} },
{/*13 LEF */ 1, 0x02, 0x02, {{"LF "}, {""}} },
{/*14 REFRESH */ 1, 0x01, 0x01, {{"RF "}, {""}} }
};
int amode, /* Addressing Mode */
rmode, /* Residence Mode */
i, /* Counter */
len; /* Length of attr string */
char *ptr; /* temp ptr */
memset(attrs, '\0', ATTRSIZE); /* Start out right */
/*----------------------------------------------------------------+
| Get the AMODE |
| Bits 6 & 7 used for the actual member |
| Bits 4 & 5 used for an alias to an actual member |
+----------------------------------------------------------------*/
if (!alias_flg)
{
amode =(ftbo[1] & PDSMAMOD);/* Get the amode */
switch (amode) /* Now determine what amode is */
{
case 0x00:
case BIT7:
strcpy(attrs, "A24 ");
break;
case BIT6:
strcpy(attrs, "A31 ");
break;
case BIT6+BIT7:
strcpy(attrs, "AANY");
break;
default:
strcpy(attrs, "A?? ");
break;
}
}
else
{ /* Determine the amode & rmode */
amode =(ftbo[1] & PDSAAMOD);/* Get the amode */
switch (amode) /* Now determine what amode is */
{
case 0x00:
case BIT5:
strcpy(attrs, "A24 ");
break;
case BIT4:
strcpy(attrs, "A31 ");
break;
case BIT4+BIT5:
strcpy(attrs, "AANY");
break;
default:
strcpy(attrs, "A?? ");
break;
}
}
/*----------------------------------------------------------------+
| Get the RMODE |
| Bit 3 used for both alias's and actual members |
+----------------------------------------------------------------*/
rmode =(ftbo[1] & PDSLRMOD);/* Get the rmode */
if (rmode == 0x10) /* Determine the rmode */
strcat(attrs, " RANY");
else
strcat(attrs, " R24 ");
/*----------------------------------------------------------------+
| Get the other attributes |
+----------------------------------------------------------------*/
strcat(attrs," "); /* add a space */
len=strlen(attrs);
for (i=0; i (ATTRSIZE - ATTRITSZ))
{
ptr = attrs + (len-1);
ptr += sprintf(ptr, "\n%*s", (80 - ATTRSIZE), " ");
len = 0;
}
strcat(attrs, /* Look carefully now... */
ATab[i].txt[ \
(((atr[ATab[i].Num] & ATab[i].And)==ATab[i].Cmp) ? 0 : 1) \
]);
len += ATTRITSZ;
}
}
#pragma eject
/*-------------------------------------------------------------------+
| FUNCTION: ParsePath |
| PURPOSE: Parse a path into fn, ft, fm and member. |
| AREAS: LIBNAME |
| EXTREF: memset, strcpy, strupr, strchr, strstr, strtok, sizeof|
| STATIC: - |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
static int ParsePath(
char *path, /* pathname */
LIBNAME *LibN /* ptr to LIBNAME struct to build */
)
{
int i; /* Counter */
char *ptr, /* Pointer for tokenizing path */
*lparen, /* ptr to left parenthesis */
*memptr, /* ptr to the word MEM||MEMBER */
fm_STAR[2] = "*", /* Default filemode. */
ft_LDLB[9] = "LOADLIB"; /* Default filetype. */
memset(LibN, '\0', sizeof(LibN));
strcpy(LibN->path, path); /* Copy to work area. */
strupr(LibN->path); /* Upper case */
/*----------------------------------------------------------------+
| Do we have a member name? |
+----------------------------------------------------------------*/
if ( (lparen = strchr(LibN->path, '(') ) != 0)
{
if (strchr(LibN->path, ' '))/* Is this a cms style name? */
{ /* Find where member is in string */
if ((memptr = strstr(lparen, "MEM")) != 0)
{ /* Blank out the word MEM||MEMBER */
while(*memptr != ' ')
*memptr++ = ' ';
}
else
{ /* MEM not found!! ERROR */
return(FAIL); /* use return, nothing alloc'd yet*/
}
} /* cms style name? */
} /* lparen ? */
else
{ /* No member, call access, return*/
return(DO_ACCESS); /*use return, nothing alloc'd yet*/
}
/*----------------------------------------------------------------+
| Tokenize the string -- remember where each piece is |
+----------------------------------------------------------------*/
ptr = strtok(LibN->path, " .()");
i=0;
while (ptr != NULL) /* Tokenize it.. */
{
LibN->ptr.a[i] = ptr; /* Pt. to this piece of string */
ptr = strtok(NULL, " .()");
i++;
}
/*----------------------------------------------------------------+
| Fill in any missing data -- ie. ft or fm |
+----------------------------------------------------------------*/
if (i <= 3)
{
/* pt MEMNAME to the member name */
LibN->ptr.s.memname = LibN->ptr.a[i-1];
if (i == 3) /* we got fn ft and a member */
{
/* Copy Fm_STAR to fm */
LibN->ptr.s.fm = LibN->ptr.s.memname + \
strlen(LibN->ptr.s.memname) + 1;
strcpy(LibN->ptr.s.fm, fm_STAR);
}
else if (i == 2) /* Put a ft = LOADLIB & fm = * */
{
/* Copy ft_LDLB to ft */
LibN->ptr.s.ft = LibN->ptr.s.memname + \
strlen(LibN->ptr.s.memname) + 1;
strcpy(LibN->ptr.s.ft, ft_LDLB);
/* Copy fm_STAR to fm */
LibN->ptr.s.fm = LibN->ptr.s.ft + \
strlen(LibN->ptr.s.ft) + 1;
strcpy(LibN->ptr.s.fm, fm_STAR);
}
else
{
return(FAIL); /* Not a valid filename sequence */
/* ddn: not supported. */
}
}
return(OK);
}
#pragma eject
/*-------------------------------------------------------------------+
| FUNCTION: AddFT |
| PURPOSE: Add the filetype of LOADLIB to the given fname by |
| building a LIBNAME struct. |
| AREAS: LIBNAME |
| EXTREF: sprintf, strupr |
| STATIC: - |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
static void AddFT(
char *fn, /* LOADLIB fn */
LIBNAME *LibN /* ptr to LIBNAME struct to build */
)
{
char *ptr; /* temp ptr */
ptr = LibN->path; /* Start out right */
LibN->ptr.s.fn = ptr; /* Get the fn */
ptr += sprintf(ptr, "%s\0", fn);
ptr++;
strupr(LibN->ptr.s.fn); /* Uppercase user input */
LibN->ptr.s.ft = ptr; /* add the ft */
ptr += sprintf(ptr, "%s\0 ", "LOADLIB");
ptr++;
LibN->ptr.s.fm = ptr; /* add the fm */
ptr += sprintf(ptr, "%s\0 ", "*");
ptr++;
LibN->ptr.s.memname = ptr; /* Null out the membername */
ptr = '\0';
}
#pragma eject
/*-------------------------------------------------------------------+
| FUNCTION: InitLdLb |
| PURPOSE: Open LOADLIB file, malloc space for an FSCB, FST, and |
| a rdbuff. Also, read the LOADLIB header and move the |
| file pointer to the first directory record. |
| AREAS: LIBNAME, CMSFILE(CMSFSCB, CMSFST), LHDR |
| EXTREF: malloc, memset memcmp, memcpy, cmsstate, cmsopen, |
| cmsread |
| STATIC: - |
| NOTES: |
| END |
+-------------------------------------------------------------------*/
static int InitLdLb(
LIBNAME *Lname, /* CMS LOADLIB fn ft fm(member */
CMSFILE **fptr, /* Ptr to CMSFILE struct. */
char **rdbuff /* CMSREAD buffer */
)
{
LHDR *hdr; /* Points to LOADLIB header. */
/*----------------------------------------------------------------+
| Allocate the CMSFILE Structure (an FSCB & an FST). |
+----------------------------------------------------------------*/
if((*fptr = (CMSFILE *) malloc(sizeof(CMSFILE))) == NULL)
{
return(FAIL);
}
/*----------------------------------------------------------------+
| Set up the CMSFILE Structure. |
+----------------------------------------------------------------*/
/* Filename */
memset((*fptr)->fscb.fn, ' ', 8);
memcpy((*fptr)->fscb.fn, Lname->ptr.s.fn, strlen(Lname->ptr.s.fn));
/* Filetype */
memset((*fptr)->fscb.ft, ' ', 8);
memcpy((*fptr)->fscb.ft, Lname->ptr.s.ft, strlen(Lname->ptr.s.ft));
/* Filemode */
memset((*fptr)->fscb.fm, ' ', 2);
memcpy((*fptr)->fscb.fm, Lname->ptr.s.fm, strlen(Lname->ptr.s.fm));
/*----------------------------------------------------------------+
| STATE the LOADLIB file and fill in FSCB. |
+----------------------------------------------------------------*/
if ((cmsstate(&((*fptr)->fscb), &((*fptr)->fst))) !=0)
{
return(FAIL);
}
/*----------------------------------------------------------------+
| Just to make sure, compare the fileid from the FST to the file- |
| id in the FSCB. |
+----------------------------------------------------------------*/
if (memcmp((*fptr)->fscb.fn,(*fptr)->fst.fname,16) != 0)
return(FAIL);
/*----------------------------------------------------------------+
| Copy important fields from the FST to the FSCB. Just for |
| completeness, reset unused fields. |
+----------------------------------------------------------------*/
/* Filemode. */
memcpy((*fptr)->fscb.fm,(*fptr)->fst.fmode,sizeof((*fptr)->fscb.fm));
/* LRECL. */
(*fptr)->fscb.size = (*fptr)->fst.lrecl;
/* RECFM. */
(*fptr)->fscb.fv = (*fptr)->fst.recfm;
/* Command. */
memset((*fptr)->fscb.comm,' ',sizeof((*fptr)->fscb.comm));
/* Old-style RECNO, NOREC. */
(*fptr)->fscb.itno = (*fptr)->fscb.noit = 0;
/* New-style RECNO, NOREC. */
(*fptr)->fscb.anit = (*fptr)->fscb.aitn = 0;
/*----------------------------------------------------------------+
| malloc the read buffer - get enough for a record of the LOADLIB|
+----------------------------------------------------------------*/
if ((*rdbuff = (char *) malloc((*fptr)->fst.lrecl)) == NULL)
{
return(FAIL);
}
/*----------------------------------------------------------------+
| Open the LOADLIB, fill in the correct buffer data, and read |
| the header record. Confirm that the file is indeed a LOADLIB. |
| Set the FSCB so the first read is for the first dir ent rec. |
+----------------------------------------------------------------*/
if (cmsopen(&((*fptr)->fscb)))
return(FAIL);
(*fptr)->fscb.aitn = 1; /* RECNO = 1. */
(*fptr)->fscb.anit = 1; /* NOREC = 1. */
(*fptr)->fscb.buff = *rdbuff; /* BUFFER=rdbuff. */
/* BSIZE=buffsize. */
(*fptr)->fscb.size = (*fptr)->fst.lrecl;
/* Read the header record. */
if (cmsread(&((*fptr)->fscb)))
return(FAIL);
hdr = (struct LHDR *) *rdbuff; /* Verify that this is a loadlib. */
if (memcmp(hdr->ident,"LIBPDS",sizeof(hdr->ident)) != 0)
return(FAIL);
/*----------------------------------------------------------------+
| Set the file pointer to the first directory record. |
+----------------------------------------------------------------*/
(*fptr)->fscb.aitn = hdr->dir;
return(OK);
}
|