/*-------------------------------------------------------------------+ | | | 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 | | #include -- 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 \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 | | #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 /* Needed for printf() etc. */ #include /* Needed for cmsopen, cmsread,etc*/ #include /* Needed for strcpy, memcpy, etc.*/ #include /* 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); }