home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 181_01 / ldirsort.c < prev    next >
Text File  |  1985-03-10  |  12KB  |  509 lines

  1.  /*    LDIR     Library Directory display program */
  2. #define    VERSION        1 
  3. #define    REVISION    00
  4. #define MOD_DATE    "82-11-14"
  5.  
  6. /*    Copyright (c) 1982 by Gary P. Novosielski.
  7.     All rights reserved.
  8.  
  9.     Permission is hereby granted for noncommercial use.
  10.     Duplication or use of this or any derivative work for
  11.     commercial advantage without prior written consent of
  12.     the author is prohibited.
  13.  
  14. LIFO Revision Summary:
  15.  
  16.         ?.??    83-09-17        
  17. Modified as LDIRSORT.COM.  Will optionally generate 'NAMES.SUB'
  18. file for use by CAT2.COM.  Will not handle LBR names exceeding
  19. seven chars in length.  This to allow for the '-' required by the
  20. PDS catalog system (i.e. CAT1.COM).  I must consider this program a
  21. kludge, but it works.  I left intact most of Gary N.'s code.  Most
  22. changes are additions to his source.  Control structure is unchanged
  23. except for the exit() if the user tries to catalog an LBR whose name
  24. is eight chars long.  
  25.   Also modified program to produce sorted report.  Filenames are
  26. arranged vertically, as in UDIR.COM, instead of horizontally, as in
  27. SD.COM.  With this change, both the file output and the screen
  28. output use the new function FORMNAM2(), instead of the original
  29. function, FORMNAME().
  30.   Also, I did not modify the original programs ability to handle
  31. multiple command-line arguments.  It still lists the internal files
  32. fo≥ a≤ man∙ file≤ a≤ i⌠ diΣ previously, unless user asks for more
  33. than one NAMES.SUB files.  Thus¼ iµ thσ prograφ i≤ run thus:
  34.                  A> ldirc file1 - file2 file3<cr>
  35. then the NAMES.SUB file will have the catalog information only for 
  36. FILE2.LBR.  This keeps garbage out of your MAST.CAT file.
  37.  
  38.                 Joe S. Vogler
  39.         3622 Highland Lakes Drive
  40.         Kingwood, Texas  77339
  41.         (713) 358-7586 (evenings)
  42.  
  43.     1.00    82-11-14    Initial source release
  44.         Gary P. Novosielski
  45.  
  46. Program Description:
  47.     This program is intended for use on RCPM systems to
  48.     allow callers to see the contents of the directories
  49.     of .LBR files on the system.  You probably won't need
  50.     it on your home system, since the -L function of LU.COM
  51.     provides this ability.  Since LU is not active on
  52.     remote systems, a program like this is necessary
  53.     to allow you to see member names in a library without
  54.     your having to download the library first.
  55.  
  56. Syntax:
  57.         LDIR <name1> [<name2>...[<nameN>]]
  58.     where <name1> etc. are library names of the form:
  59.         [<drive>:]<lbrname>[.<ext>]
  60. ==defaults==>     Current         LBR
  61.          drive
  62.  
  63.     Ambiguous names are not permitted.  Typing LDIR with
  64.     no arguments presents a help message.
  65. */
  66.  
  67. #include "bdscio.h"
  68.  
  69. /* Pseudo typedef's */
  70. #define FLAG        char
  71. #define FD        int
  72.  
  73. /* Number of displayed entries per line: */
  74. #define NWIDE        4
  75.  
  76. /* EXTERNALS */
  77. FD   lbrfile;             /* fd for library file    */
  78. char lbrname[20];
  79. int outbuf;                       /* JSV */
  80. int catflag;             /* add to names.sub while TRUE */
  81. char flabel[20];        /* for copy of lbrname[20] */
  82.  
  83. int strcmp();        /*    JSV        */
  84. #define MAXLINES    300
  85. char *ftab[MAXLINES];    /*            */
  86. int fcount;        /*    for sorting    */
  87. char *allocp;        /*            */
  88.  
  89. #define FROM_START    0
  90. #define AS_INPUT    0
  91.  
  92. FLAG lbropen;
  93. int  entries, freeent;
  94.  
  95. /* Entry Size */
  96. #define ESIZE        32
  97.  
  98. /* Entries per sector */
  99. #define EPS        (SECSIZ / ESIZE)
  100.  
  101. /* Structure of a directory entry */
  102. struct direntry
  103. {
  104.     char status;    /* Possible values */
  105. #define  ACTIVE            0x00
  106. #define  KILLED            0xFE
  107. #define     VIRGIN            0xFF
  108.     char id[8+3];     /* filename.ext */
  109.     unsigned indx;    /* Pointer to first sector */
  110.     unsigned size;    /* Size of member in sectors */
  111.             /* Future expansion space */
  112. #define EXPSIZ            16
  113.     char expand[EXPSIZ];
  114. }
  115. *directory, *curentry;    /* two pointers to such a beast */
  116.  
  117. /*
  118.         END OF EXTERNALS
  119. */
  120.  
  121. main(argc,argv)
  122. int  argc;
  123. char **argv;
  124. {
  125.     int i;        /* JSV: temporary counter    */
  126.     printf(
  127.       "Library DIRectory   Ver:%d.%02d   %s\n%s\n",
  128.       VERSION,REVISION,MOD_DATE,
  129.       "Copyright (c) 1982  Gary P. Novosielski");
  130.     puts("Modified 09/17/83 for sorted output ");
  131.     puts("and for optional NAMES.SUB file");
  132.     puts("\n   by Joe S. Vogler  83/09/17 ");
  133.     puts("\n\nPress CTRL-S to pause; CTRL-C to cancel\n");
  134.     if (bdos(12)%256 < 0x20) 
  135.     abend("\nRequires CP/M 2.0 or better");
  136.  
  137.     /* Initialize flags */
  138.     lbropen = FALSE;
  139.     directory = NULL;
  140.     catflag = FALSE;                            /* JSV */
  141.  
  142.     if (argc < 2)
  143.     {
  144.     puts("\n\nCorrect syntax is:");
  145.     puts("\n\n\tLDIR <name1> [<name2>]...");
  146.     puts("\n\nwhere <name1>, <name2>, etc.");è    puts(" are library names.");
  147.     puts("\nFiletype .LBR is assumed if not specified.");
  148.     puts("\nAmbiguous names are not allowed.");
  149.     puts("\n\n ** NEW:  An option to create NAMES.SUB file for ONE");
  150.     puts("\nLBR arg.  Just preceed desired LBR arg with a 'DASH' ");
  151.     puts("\nplus a SPACE...as in:  A> ldirsort <lbr1> - <lbr2><CR>");
  152.     puts("\n(NAMES.SUB file will be created for <lbr2>).");
  153.     puts("\n        Joe S. Vogler  713-358-7586, evenings\n");
  154.     }
  155.     else
  156.     {
  157.     /* Process command line arguments */
  158.     while(--argc)
  159.     {
  160.         if (argv[1][0] == '-')        {
  161.         if (catflag)    {
  162.             exit(puts("\nERROR:  No more than one NAMES.SUB files!"));
  163.         }
  164.         fcreat("names.sub",outbuf=sbrk(BUFSIZ));
  165.         catflag = TRUE;
  166.         argv++;
  167.         continue;
  168.         }
  169.  
  170.  
  171.         if (!namel(*(++argv)))  {
  172.         dirlist();
  173.             }
  174.         else
  175.         printf("\n%s not found on disk.\n",lbrname);
  176.  
  177.     }
  178.     }
  179.     /* End of command line.  Clean up and exit */
  180.  
  181.     exit();
  182. }
  183. /* End of main function */
  184.  
  185.  
  186. namel(name)
  187. /* Open *name as the current library */
  188. char *name;
  189. {
  190.     if (lbropen && close(lbrfile) == ERROR)
  191.     abend("\nCan't close library: %s",lbrname);
  192.     lbropen = FALSE;
  193.     if (isambig(name) || indexc(name,' ') != ERROR)
  194.     abend("\nBad library name: %s",name);
  195.     strcpy(lbrname,name);
  196.     if (indexc(name,'.') == ERROR)
  197.     strcat(lbrname,".LBR");
  198.     if ((lbrfile = open(lbrname,AS_INPUT)) != ERROR)
  199.     {
  200.     printf("\nLibrary: %s has ",lbrname);
  201.     readdir();
  202.     }
  203.     else
  204.     return ERROR;
  205.     lbropen = TRUE;
  206.     printf ("%d entries, %d free:",entries,freeent);
  207.     return OK;
  208. }
  209.  
  210.  
  211. FLAG avail(request)
  212. /* Return flag saying if the requested number of memory bytes
  213.    are available.  Try to make them available if possible.
  214. */
  215. unsigned request;    /* in bytes */
  216. {è    char *ptr;
  217.     unsigned  *curavail;
  218.     curavail = "\0\0";    /* Pseudo-static kluge */
  219.  
  220.     if(request < *curavail)
  221.     return TRUE;
  222.     if ((ptr = sbrk(++request - *curavail)) == ERROR)
  223.     return FALSE;
  224.  
  225.     /* If this is the first success, initialize pointer */
  226.     if (directory == NULL)
  227.     directory =  ptr;
  228.  
  229.     *curavail = request; /* Modify static for next call */
  230.     return TRUE;
  231. }
  232.  
  233.  
  234. readdir()
  235. /* Read the directory into memory */
  236. {
  237.     if (!avail(SECSIZ))
  238.     memerr();
  239.     rseek(lbrfile, 0, FROM_START);
  240.  
  241.     if (
  242.       rread(lbrfile, directory, 1) != 1
  243.       || entcmp(directory,"\0           ")
  244.       || directory->indx
  245.       || !directory->size
  246.        )
  247.     abend("no directory");
  248.  
  249.     if (directory->size > 1)
  250.     {
  251.     if (!avail(SECSIZ * directory->size))
  252.         memerr();
  253.     if (rread(lbrfile, directory+EPS, directory->size - 1)
  254.       != directory->size - 1)
  255.         abend("a bad directory");
  256.     }
  257.  
  258.     freeent = entries = EPS * directory->size;
  259.  
  260.     for(
  261.       curentry = directory;
  262.       curentry->status != VIRGIN && freeent;
  263.       ++curentry
  264.        )
  265.     --freeent;
  266. }
  267.  
  268.  
  269.  
  270. memerr()è{
  271.     abend("run out of memory");
  272. }
  273.  
  274.  
  275. int indexc(s, c)
  276. /* Search string *s for character c.  Return offset */
  277. char *s, c;
  278. {
  279.     int i;
  280.     for (i = 0; *s; i++) 
  281.     if(*s++ == c)
  282.         return i;
  283.     return ERROR;
  284. }
  285.  
  286.  
  287. abend(p1, p2, p3, p4)
  288. /* Terminate program with error message */
  289. {
  290.     printf(p1, p2, p3, p4);
  291.     puts("\n\nFor help, type LDIR alone.");
  292.     exit();
  293. }
  294.  
  295. bitcmp(a, b, count, mask)
  296. /* compare string a to string b ignoring some bits of each */
  297. char *a, *b, mask;
  298. int count;
  299. {
  300.     int r;
  301.     while(count--)
  302.     if (r = (*a++ & mask) - (*b++ & mask))
  303.         return r;
  304.     return 0;
  305. }
  306.  
  307.  
  308.  
  309. dirlist()
  310. /* List the directory of the current library, and return number
  311.    of free entries
  312. */
  313. {
  314.     char name[20], linbuf[20];
  315.     int  row, col, nrow, index, pcount, i;
  316.     unsigned del, act;
  317.  
  318.     fcount = 0;        /* JSV                */
  319.     curentry = directory;
  320.     if (catflag)  {                          /* JSV */
  321.         strcpy(flabel,lbrname);
  322.         if( *(flabel+1) == ':' ) { strcpy(flabel,flabel+2); }
  323.         if( *(flabel+8) == '.' ) {
  324.             toolong(lbrname); 
  325.                 unlink(outbuf);
  326.                 exit();
  327.     }
  328.     }
  329.     for ((act = del = 0, i = entries - freeent); --i;)
  330.     {è    if ((++curentry)->status == ACTIVE) 
  331.     {
  332. bufin:                                /* JSV    */
  333.         strcpy3(linbuf, curentry);
  334.         if (( allocp = sbrk( strlen( linbuf) + 1)) == NULL )
  335.         exit(puts("out of allocation space\n"));
  336.         ftab[fcount++] = allocp;
  337.         strcpy( allocp, linbuf);        /* JSV */
  338.  
  339.         ++act;
  340.     }
  341.     else
  342.         ++del;
  343.     }
  344. bufsort:
  345.         qsort(ftab, fcount, 2, &strcmp);
  346.  
  347. bufcat:
  348.     if (catflag)            /* JSV: only catalog the first LBR */
  349.     {
  350.         fprintf(outbuf,"-%s\n",flabel);
  351.  
  352.         for (i = 0; i < fcount; i++)    {
  353.         formnam2( linbuf, ftab[i]);
  354.         strcat( linbuf, "\n");
  355.         fputs( linbuf, outbuf);
  356.         }
  357.         putc(CPMEOF, outbuf);
  358.         jclose(outbuf);
  359.     }
  360. bufout:
  361.     nrow = ( fcount % NWIDE ? fcount/NWIDE + 1 : fcount/NWIDE );
  362.     for ( row = 0, pcount = 0 ; row < nrow ; row++)
  363.     {
  364.         for ( col = 0; col < NWIDE; col++, pcount++ )
  365.         {
  366.             putchar( pcount % NWIDE ? '\t' : '\n');    
  367.             index = row + (nrow * col);
  368.             if ( index < fcount )    {
  369.                 printf("%-8s", formnam2(linbuf, ftab[index]));
  370.             }
  371.         }
  372.     }
  373.     printf("\n Active entries: %u, Deleted: %u, Free: %u, Total: %u.\n",
  374.       ++act, del, freeent, entries);
  375.     return --act;
  376. }
  377.  
  378.  
  379. /*
  380. formname(dst,src)
  381. /* form a string in dst from a standard format name in src */
  382. char *dst, *src;
  383. {
  384.     int i,j;
  385.     j = 0;
  386.  
  387. /* Remove attributes first so compares will work */
  388.     for (i = 1; i < 12; i++)
  389.     src[i] &= 0x7F;
  390.     for (i = 1; i < 9; i++)
  391.     {
  392.     if (src[i] == ' ')
  393.         break;
  394.     dst[j++] = src[i];
  395.     }è    if (src[9] != ' ')
  396.     dst[j++] = '.';
  397.     for (i = 9; i < 12; i++)
  398.     {
  399.     if (src[i] == ' ')
  400.         break;
  401.     dst[j++] = src[i];
  402.     }
  403.     dst[j] = '\0';
  404.     return dst;
  405. }
  406. */
  407.  
  408.  
  409. formnam2(dst,src)    /* JSV: Version for qsort table entries */
  410. /* form a string in dst from a standard format name in src */
  411. char *dst, *src;
  412. {
  413.     int i,j;
  414.     j = 0;
  415.  
  416. /* Remove attributes first so compares will work */
  417.     for (i = 0; i < 11; i++)
  418.     src[i] &= 0x7F;
  419.     for (i = 0; i < 8; i++)
  420.     {
  421.     if (src[i] == ' ')
  422.         break;
  423.     dst[j++] = src[i];
  424.     }è/*
  425.   if (src[8] != ' ')
  426. */
  427.     dst[j++] = '.';
  428.     for (i = 8; i < 11; i++)
  429.     {
  430.     if (src[i] == ' ')
  431.         break;
  432.     dst[j++] = src[i];
  433.     }
  434.     dst[j] = '\0';
  435.     return dst;
  436. }
  437.  
  438.  
  439. int isambig(name)
  440. /* Return TRUE if name is ambiguous */
  441. char *name;
  442. {
  443.     char c;
  444.  
  445.     while (c = *name++)
  446.     if (c == '*' || c == '?') 
  447.         return TRUE;
  448.     return FALSE;
  449. }
  450.  
  451. entcmp(a,b)
  452. /* Compare two directory entries. Note that status is major
  453.    sort field.
  454. */
  455. char *a, *b;
  456. {
  457.     int  i, r;
  458.  
  459.     for (i = (1+8+3); i--; a++, b++)
  460.     if ((r = *a - *b) && *b != '?')
  461.         return r;
  462.     return 0;
  463. }
  464.  
  465.  
  466.  
  467. int strcmp(s,t)
  468. char **s, **t;
  469. {
  470.     char *s1, *t1;
  471.     s1 = *s;
  472.     t1 = *t;
  473.     int i;
  474.     i = 0;
  475.     while (s1[i] == t1[i])
  476.         if (s1[i++] == '\0')
  477.             return 0;
  478.     return s1[i] - t1[i];
  479. }
  480.  
  481.  
  482.  
  483. toolong(s)
  484. int *(s);
  485. {
  486.    printf("\n\nERROR!!");
  487.    printf("\n\n  Cannot catalog %s, because...",s);
  488.    printf("\n  Library NAME cannot exceed 7 characters");
  489.    printf("\n\n Rename LBR file and rerun.");
  490. }
  491.  
  492. jclose(buf)
  493. int *buf;
  494. {    fflush(buf)╗ 
  495.     fclose(buf);
  496.     puts("\n>>>> File NAMES.SUB created on DEFAULT drive <<<<");
  497. }
  498.  
  499. strcpy3( dst, src,)
  500. char *dst, *src;
  501. {
  502.     int i, j;
  503.     src++;
  504.     for ( i = 0; i < 11; i++)
  505.         *dst++ = *src++;
  506.     *dst = *src = NULL;
  507. }
  508. /*
  509. */