www.sas.com > Service and Support > Technical Support
 
Technical Support SAS - The power to know(tm)
  TS Home | Intro to Services | News and Info | Contact TS | Site Map | FAQ | Feedback


/*-------------------------------------------------------------------+
|                                                                    |
|                      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);

   }


Copyright (c) 2000 SAS Institute Inc. All Rights Reserved.
Terms of Use & Legal Information | Privacy Statement