/* LDIR Library Directory display program */ #define VERSION 1 #define REVISION 00 #define MOD_DATE "82-11-14" /* Copyright (c) 1982 by Gary P. Novosielski. All rights reserved. Permission is hereby granted for noncommercial use. Duplication or use of this or any derivative work for commercial advantage without prior written consent of the author is prohibited. LIFO Revision Summary: 1.00 82-11-14 Initial source release Gary P. Novosielski Program Description: This program is intended for use on RCPM systems to allow callers to see the contents of the directories of .LBR files on the system. You probably won't need it on your home system, since the -L function of LU.COM provides this ability. Since LU is not active on remote systems, a program like this is necessary to allow you to see member names in a library without your having to download the library first. Syntax: LDIR [...[]] where etc. are library names of the form: [:][.] ==defaults==> Current LBR drive Ambiguous names are not permitted. Typing LDIR with no arguments presents a help message. */ #include "bdscio.h" /* Pseudo typedef's */ #define FLAG char #define FD int /* Number of displayed entries per line: */ #define NWIDE 4 /* EXTERNALS */ FD lbrfile; /* fd for library file */ char lbrname[20]; #define FROM_START 0 #define AS_INPUT 0 FLAG lbropen; int entries, freeent; /* Entry Size */ #define ESIZE 32 /* Entries per sector */ #define EPS (SECSIZ / ESIZE) /* Structure of a directory entry */ struct direntry { char status; /* Possible values */ #define ACTIVE 0x00 #define KILLED 0xFE #define VIRGIN 0xFF char id[8+3]; /* filename.ext */ unsigned indx; /* Pointer to first sector */ unsigned size; /* Size of member in sectors */ /* Future expansion space */ #define EXPSIZ 16 char expand[EXPSIZ]; } *directory, *curentry; /* two pointers to such a beast */ /* END OF EXTERNALS */ main (argc,argv) int argc; char **argv; { printf( "Library DIRectory Ver:%d.%02d %s\n%s\n%s", VERSION,REVISION,MOD_DATE, "Copyright (c) 1982 Gary P. Novosielski", "\nPress CTRL-S to pause; CTRL-C to cancel"); if (bdos(12)%256 < 0x20) abend("\nRequires CP/M 2.0 or better"); /* Initialize flags */ lbropen = FALSE; directory = NULL; if (argc < 2) { puts("\n\nCorrect syntax is:"); puts("\n\n\tLDIR []..."); puts("\n\nwhere , , etc."); puts(" are library names."); puts("\nFiletype .LBR is assumed if not specified."); puts("\nAmbiguous names are not allowed."); } else { /* Process command line arguments */ while(--argc) { if (!namel(*(++argv))) dirlist(); else printf("\n%s not found on disk.\n",lbrname); } } /* End of command line. Clean up and exit */ } /* End of main function */ namel(name) /* Open *name as the current library */ char *name; { if (lbropen && close(lbrfile) == ERROR) abend("\nCan't close library: %s",lbrname); lbropen = FALSE; if (isambig(name) || indexc(name,' ') != ERROR) abend("\nBad library name: %s",name); strcpy(lbrname,name); if (indexc(name,'.') == ERROR) strcat(lbrname,".LBR"); if ((lbrfile = open(lbrname,AS_INPUT)) != ERROR) { printf("\nLibrary: %s has ",lbrname); readdir(); } else return ERROR; lbropen = TRUE; printf ("%d entries, %d free:",entries,freeent); return OK; } FLAG avail(request) /* Return flag saying if the requested number of memory bytes are available. Try to make them available if possible. */ unsigned request; /* in bytes */ { char *ptr; unsigned *curavail; curavail = "\0\0"; /* Pseudo-static kluge */ if(request < *curavail) return TRUE; if ((ptr = sbrk(++request - *curavail)) == ERROR) return FALSE; /* If this is the first success, initialize pointer */ if (directory == NULL) directory = ptr; *curavail = request; /* Modify static for next call */ return TRUE; } readdir() /* Read the directory into memory */ { if (!avail(SECSIZ)) memerr(); rseek(lbrfile, 0, FROM_START); if ( rread(lbrfile, directory, 1) != 1 || entcmp(directory,"\0 ") || directory->indx || !directory->size ) abend("no directory"); if (directory->size > 1) { if (!avail(SECSIZ * directory->size)) memerr(); if (rread(lbrfile, directory+EPS, directory->size - 1) != directory->size - 1) abend("a bad directory"); } freeent = entries = EPS * directory->size; for( curentry = directory; curentry->status != VIRGIN && freeent; ++curentry ) --freeent; } memerr() { abend("run out of memory"); } int indexc(s, c) /* Search string *s for character c. Return offset */ char *s, c; { int i; for (i = 0; *s; i++) if(*s++ == c) return i; return ERROR; } abend(p1, p2, p3, p4) /* Terminate program with error message */ { printf(p1, p2, p3, p4); puts("\n\nFor help, type LDIR alone."); exit(); } bitcmp(a, b, count, mask) /* compare string a to string b ignoring some bits of each */ char *a, *b, mask; int count; { int r; while(count--) if (r = (*a++ & mask) - (*b++ & mask)) return r; return 0; } formname(dst,src) /* form a string in dst from a standard format name in src */ char *dst, *src; { int i,j; j = 0; /* Remove attributes first so compares will work */ for (i = 1; i < 12; i++) src[i] &= 0x7F; for (i = 1; i < 9; i++) { if (src[i] == ' ') break; dst[j++] = src[i]; } if (src[9] != ' ') dst[j++] = '.'; for (i = 9; i < 12; i++) { if (src[i] == ' ') break; dst[j++] = src[i]; } dst[j] = '\0'; return dst; } int isambig(name) /* Return TRUE if name is ambiguous */ char *name; { char c; while (c = *name++) if (c == '*' || c == '?') return TRUE; return FALSE; } entcmp(a,b) /* Compare two directory entries. Note that status is major sort field. */ char *a, *b; { int i, r; for (i = (1+8+3); i--; a++, b++) if ((r = *a - *b) && *b != '?') return r; return 0; } dirlist() /* List the directory of the current library, and return number of free entries */ { char name[20]; int i; unsigned del, act; curentry = directory; for ((act = del = 0, i = entries - freeent); --i;) { if ((++curentry)->status == ACTIVE) { putchar(act % NWIDE ? '\t' : '\n'); formname(name, curentry); printf("%-8s", name); ++act; } else ++del; } printf("\n Active entries: %u, Deleted: %u, Free: %u, Total: %u.\n", ++act, del, freeent, entries); return --act; }