home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug056.arc / LDIR.LBR / LDIR.CQ / LDIR.C
Text File  |  1979-12-31  |  7KB  |  335 lines

  1. /*    LDIR     Library Directory display program */
  2.  
  3. #define    VERSION        1 
  4. #define    REVISION    00
  5. #define MOD_DATE    "82-11-14"
  6.  
  7. /*    Copyright (c) 1982 by Gary P. Novosielski.
  8.     All rights reserved.
  9.  
  10.     Permission is hereby granted for noncommercial use.
  11.     Duplication or use of this or any derivative work for
  12.     commercial advantage without prior written consent of
  13.     the author is prohibited.
  14.  
  15. LIFO Revision Summary:
  16.     1.00    82-11-14    Initial source release
  17.         Gary P. Novosielski
  18.  
  19. Program Description:
  20.     This program is intended for use on RCPM systems to
  21.     allow callers to see the contents of the directories
  22.     of .LBR files on the system.  You probably won't need
  23.     it on your home system, since the -L function of LU.COM
  24.     provides this ability.  Since LU is not active on
  25.     remote systems, a program like this is necessary
  26.     to allow you to see member names in a library without
  27.     your having to download the library first.
  28.  
  29. Syntax:
  30.         LDIR <name1> [<name2>...[<nameN>]]
  31.     where <name1> etc. are library names of the form:
  32.         [<drive>:]<lbrname>[.<ext>]
  33. ==defaults==>     Current         LBR
  34.          drive
  35.  
  36.     Ambiguous names are not permitted.  Typing LDIR with
  37.     no arguments presents a help message.
  38. */
  39.  
  40. #include "bdscio.h"
  41.  
  42. /* Pseudo typedef's */
  43. #define FLAG        char
  44. #define FD        int
  45.  
  46. /* Number of displayed entries per line: */
  47. #define NWIDE        4
  48.  
  49. /* EXTERNALS */
  50. FD   lbrfile;             /* fd for library file    */
  51. char lbrname[20];
  52.  
  53. #define FROM_START    0
  54. #define AS_INPUT    0
  55.  
  56. FLAG lbropen;
  57. int  entries, freeent;
  58.  
  59. /* Entry Size */
  60. #define ESIZE        32
  61.  
  62. /* Entries per sector */
  63. #define EPS        (SECSIZ / ESIZE)
  64.  
  65. /* Structure of a directory entry */
  66. struct direntry
  67. {
  68.     char status;    /* Possible values */
  69. #define  ACTIVE            0x00
  70. #define  KILLED            0xFE
  71. #define     VIRGIN            0xFF
  72.     char id[8+3];     /* filename.ext */
  73.     unsigned indx;    /* Pointer to first sector */
  74.     unsigned size;    /* Size of member in sectors */
  75.             /* Future expansion space */
  76. #define EXPSIZ            16
  77.     char expand[EXPSIZ];
  78. }
  79. *directory, *curentry;    /* two pointers to such a beast */
  80.  
  81. /*
  82.         END OF EXTERNALS
  83. */
  84.  
  85. main (argc,argv)
  86. int  argc;
  87. char **argv;
  88. {
  89.     printf(
  90.       "Library DIRectory   Ver:%d.%02d   %s\n%s\n%s",
  91.       VERSION,REVISION,MOD_DATE,
  92.       "Copyright (c) 1982  Gary P. Novosielski",
  93.       "\nPress CTRL-S to pause; CTRL-C to cancel");
  94.     if (bdos(12)%256 < 0x20) 
  95.     abend("\nRequires CP/M 2.0 or better");
  96.  
  97.     /* Initialize flags */
  98.     lbropen = FALSE;
  99.     directory = NULL;
  100.  
  101.  
  102.     if (argc < 2)
  103.     {
  104.     puts("\n\nCorrect syntax is:");
  105.     puts("\n\n\tLDIR <name1> [<name2>]...");
  106.     puts("\n\nwhere <name1>, <name2>, etc.");
  107.     puts(" are library names.");
  108.     puts("\nFiletype .LBR is assumed if not specified.");
  109.     puts("\nAmbiguous names are not allowed.");
  110.     }
  111.     else
  112.     {
  113.     /* Process command line arguments */
  114.     while(--argc)
  115.     {
  116.         if (!namel(*(++argv)))
  117.         dirlist();
  118.         else
  119.         printf("\n%s not found on disk.\n",lbrname);
  120.  
  121.     }
  122.     }
  123.     /* End of command line.  Clean up and exit */
  124. }
  125. /* End of main function */
  126.  
  127.  
  128. namel(name)
  129. /* Open *name as the current library */
  130. char *name;
  131. {
  132.     if (lbropen && close(lbrfile) == ERROR)
  133.     abend("\nCan't close library: %s",lbrname);
  134.     lbropen = FALSE;
  135.     if (isambig(name) || indexc(name,' ') != ERROR)
  136.     abend("\nBad library name: %s",name);
  137.     strcpy(lbrname,name);
  138.     if (indexc(name,'.') == ERROR)
  139.     strcat(lbrname,".LBR");
  140.     if ((lbrfile = open(lbrname,AS_INPUT)) != ERROR)
  141.     {
  142.     printf("\nLibrary: %s has ",lbrname);
  143.     readdir();
  144.     }
  145.     else
  146.     return ERROR;
  147.     lbropen = TRUE;
  148.     printf ("%d entries, %d free:",entries,freeent);
  149.     return OK;
  150. }
  151.  
  152.  
  153. FLAG avail(request)
  154. /* Return flag saying if the requested number of memory bytes
  155.    are available.  Try to make them available if possible.
  156. */
  157. unsigned request;    /* in bytes */
  158. {
  159.     char *ptr;
  160.     unsigned  *curavail;
  161.     curavail = "\0\0";    /* Pseudo-static kluge */
  162.  
  163.     if(request < *curavail)
  164.     return TRUE;
  165.     if ((ptr = sbrk(++request - *curavail)) == ERROR)
  166.     return FALSE;
  167.  
  168.     /* If this is the first success, initialize pointer */
  169.     if (directory == NULL)
  170.     directory =  ptr;
  171.  
  172.     *curavail = request; /* Modify static for next call */
  173.     return TRUE;
  174. }
  175.  
  176.  
  177. readdir()
  178. /* Read the directory into memory */
  179. {
  180.     if (!avail(SECSIZ))
  181.     memerr();
  182.     rseek(lbrfile, 0, FROM_START);
  183.  
  184.     if (
  185.       rread(lbrfile, directory, 1) != 1
  186.       || entcmp(directory,"\0           ")
  187.       || directory->indx
  188.       || !directory->size
  189.        )
  190.     abend("no directory");
  191.  
  192.     if (directory->size > 1)
  193.     {
  194.     if (!avail(SECSIZ * directory->size))
  195.         memerr();
  196.     if (rread(lbrfile, directory+EPS, directory->size - 1)
  197.       != directory->size - 1)
  198.         abend("a bad directory");
  199.     }
  200.  
  201.     freeent = entries = EPS * directory->size;
  202.  
  203.     for(
  204.       curentry = directory;
  205.       curentry->status != VIRGIN && freeent;
  206.       ++curentry
  207.        )
  208.     --freeent;
  209. }
  210.  
  211.  
  212.  
  213. memerr()
  214. {
  215.     abend("run out of memory");
  216. }
  217.  
  218.  
  219. int indexc(s, c)
  220. /* Search string *s for character c.  Return offset */
  221. char *s, c;
  222. {
  223.     int i;
  224.     for (i = 0; *s; i++) 
  225.     if(*s++ == c)
  226.         return i;
  227.     return ERROR;
  228. }
  229.  
  230.  
  231. abend(p1, p2, p3, p4)
  232. /* Terminate program with error message */
  233. {
  234.     printf(p1, p2, p3, p4);
  235.     puts("\n\nFor help, type LDIR alone.");
  236.     exit();
  237. }
  238.  
  239. bitcmp(a, b, count, mask)
  240. /* compare string a to string b ignoring some bits of each */
  241. char *a, *b, mask;
  242. int count;
  243. {
  244.     int r;
  245.     while(count--)
  246.     if (r = (*a++ & mask) - (*b++ & mask))
  247.         return r;
  248.     return 0;
  249. }
  250.  
  251.  
  252.  
  253. formname(dst,src)
  254. /* form a string in dst from a standard format name in src */
  255. char *dst, *src;
  256. {
  257.     int i,j;
  258.     j = 0;
  259.  
  260. /* Remove attributes first so compares will work */
  261.     for (i = 1; i < 12; i++)
  262.     src[i] &= 0x7F;
  263.     for (i = 1; i < 9; i++)
  264.     {
  265.     if (src[i] == ' ')
  266.         break;
  267.     dst[j++] = src[i];
  268.     }
  269.     if (src[9] != ' ')
  270.     dst[j++] = '.';
  271.     for (i = 9; i < 12; i++)
  272.     {
  273.     if (src[i] == ' ')
  274.         break;
  275.     dst[j++] = src[i];
  276.     }
  277.     dst[j] = '\0';
  278.     return dst;
  279. }
  280.  
  281.  
  282. int isambig(name)
  283. /* Return TRUE if name is ambiguous */
  284. char *name;
  285. {
  286.     char c;
  287.  
  288.     while (c = *name++)
  289.     if (c == '*' || c == '?') 
  290.         return TRUE;
  291.     return FALSE;
  292. }
  293.  
  294. entcmp(a,b)
  295. /* Compare two directory entries. Note that status is major
  296.    sort field.
  297. */
  298. char *a, *b;
  299. {
  300.     int  i, r;
  301.  
  302.     for (i = (1+8+3); i--; a++, b++)
  303.     if ((r = *a - *b) && *b != '?')
  304.         return r;
  305.     return 0;
  306. }
  307.  
  308. dirlist()
  309. /* List the directory of the current library, and return number
  310.    of free entries
  311. */
  312. {
  313.     char name[20];
  314.     int  i;
  315.     unsigned del, act;
  316.  
  317.     curentry = directory;
  318.     for ((act = del = 0, i = entries - freeent); --i;)
  319.     {
  320.     if ((++curentry)->status == ACTIVE) 
  321.     {
  322.         putchar(act % NWIDE ? '\t' : '\n');
  323.         formname(name, curentry);
  324.         printf("%-8s", name);
  325.         ++act;
  326.     }
  327.     else
  328.         ++del;
  329.     }
  330.     printf("\n Active entries: %u, Deleted: %u, Free: %u, Total: %u.\n",
  331.       ++act, del, freeent, entries);
  332.     return --act;
  333. }
  334.  
  335.