Date : Fri, 03 May 1985 18:14:42 GMT
From : bill%persci.uucp@BRL.ARPA
Subject: ldir.c and ltype.c source, for Unix
I am posting this to net.micro.cpm instead of net.sources because I believe it
to be of no interest to anybody other than a CP/M user.
Here are sources for ldir.c and ltype.c, two probably very familiar library
utilities. I acquired these from a local BBS, where they had been posted as
IBM PC utilities. It took a little effort to adapt them to our 4.2bsd
environment.
Now all that is needed is for somebody to build on these routines (and on the
'usq' I posted a few days ago to net.sources) to create a full 'lu' utility,
which would be *VERY* handy in facilitating file transfers to/from home.
I am sure some of you will improve and enhance these utilities. Please post
your upgrades so we all can share them.
Bill Swan {ihnp4|decvax|allegra|...}!uw-beaver!tikal!persci!bill
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# ldir.c
# ltype.c
# This archive created: Fri May 3 10:59:32 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'ldir.c'" '(10133 characters)'
if test -f 'ldir.c'
then
echo shar: over-writing existing file "'ldir.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'ldir.c'
X/* LDIR Library Directory display program */
X
X#define VERSION 3
X#define REVISION 1
X#define MOD_DATE "85-05-03"
X
X/*
XLegal Notices:
X Copyright (c) 1982, 1983 by Gary P. Novosielski.
X All rights reserved.
X
X Permission is hereby granted for noncommercial use.
X Use or duplication of this or any derivative work for
X commercial advantage without prior written consent
X of the author is prohibited.
X
XLIFO Revision Summary:
X 3.01 85-05-03 Modified to run under 4.2bsd. Required changing
X all ints to shorts. (Bill Swan)
X 3.00 84-29-84 Revised for use on IBM-PC running
X MS-DOS. Compiler = Lattice 'c'
X (Pete Mack)
X 2.20 83-10-13 Changed Kb size calculation to
X round upward. Added max drive
X validation. Moved copyright
X display to help section.
X 2.11 83-03-21 BDS 1.5 support.
X Size display in Kb.
X 2.10 82-12-09 Size display in sectors.
X 2.00 82-11-20 [Not released]
X 1.00 82-11-14 Initial source release
X Gary P. Novosielski
X
XProgram Description:
X This program is intended for use on RCPM systems to
X allow callers to see the contents of the directories
X of .LBR files on the system. You probably won't need
X it on your home system, since the -L function of LU.COM
X provides this ability. Since LU is not active on
X remote systems, a program like this is necessary
X to allow you to see member names in a library without
X your having to download the library first.
X
X It has been modified to run under Unix 4.2bsd, as a help
X to those of us who transfer files between our home systems
X and VAXen.
X*/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#define FALSE 0
X#define TRUE -1
X
X/* Pseudo typedef's */
X#define FLAG char
X
X/* Number of displayed entries */
X#define NWIDE 4
X
X/* EXTERNALS */
XFILE *lbrfile, *fopen(); /* fd for library file */
Xchar lbrname[20];
X
X#define FROM_START 0
X
XFLAG lbropen;
Xshort entries, freeent;
X
X/* Entry Size */
X#define ESIZE 32
X
X/* Entries per sector */
X#define EPS (SECSIZ / ESIZE)
X
X/* Structure of a directory entry */
Xstruct direntry
X{
X char status; /* Possible values */
X#define ACTIVE 0x00
X#define KILLED 0xFE
X#define VIRGIN 0xFF
X char id[8+3]; /* filename.ext */
X unsigned short indx; /* Pointer to first sector */
X unsigned short size; /* Size of member in sectors */
X unsigned short crc; /* CRC check word */
X /* Future expansion space */
X#define EXPSIZ 14
X char expand[EXPSIZ];
X}
X*directory, *curentry; /* two pointers to such a beast */
X
Xtypedef struct direntry dirtype;
X
Xchar sopt; /* size option: S, N, or K */
Xchar *drmsg; /* Max drive letter allowed */
X
X/* END OF EXTERNALS */
X#define SECSIZ 128
X#define OK 0
X#define ERROR -1
X
X
Xshort indexc(),entcmp(),bitcmp(); /*non-integer functions*/
X/************************************************
X main
X*************************************************/
X
Xmain (argc,argv)
Xunsigned argc;
Xchar *argv[];
X{
X printf(
X "Library DIRectory Ver:%d.%02d %s\n\r%s\n\r",
X VERSION,REVISION,MOD_DATE,
X "Press CTRL-S to pause; CTRL-C to cancel"
X );
X
X
X /*
X The FIRST character of the following message is actually
X used in the test for the maximum legal drive. This will
X allow sites which do not support a C compiler to easily
X find and patch this value in the object code.
X */
X drmsg = "P: is highest valid drive";
X
X
X /* Initialize flags */
X sopt = 'K'; /* Default option setting */
X lbropen = FALSE; /* No library open */
X directory = NULL; /* No directory in memory */
X
X
X if (argc < 2) /* No command line arguments */
X {
X puts("\n\rCopyright (c) 1982, 1983 by Gary P. Novosielski");
X puts("\n\r\nCorrect syntax is:");
X puts("\n\rLDIR [<option>] name1 [[<option>] [name2...[nameN]]]");
X puts("\n\r\nWhere:\tname1 through");
X puts("\n\r\tnameN\tare library names; default type: .LBR");
X puts("\n\rOptions:\n\r\t-n\tonly show names of members.");
X puts("\n\r\t-s\talso show size in sectors.");
X puts("\n\r\t-k\tlike -s, but size in Kbytes. (default)");
X puts("\n\rOption flags stay in effect for subsequent names.");
X puts("\n\rAmbiguous names are not permitted.");
X
X
X
X }
X else
X /* Process command line arguments */
X while(--argc)
X {
X if (**(++argv) == '-')
X procopt(*argv);
X else if (!namel(*argv))
X dirlist();
X else
X printf("\n\r%s not found on disk.\n\r",lbrname);
X
X }
X /* End of command line. Clean up and exit */
X}
X/* End of main function */
X
X/************************************************
X Open *name as the current library
X*************************************************/
X
Xnamel(name)
Xchar *name;
X{
X if (lbropen && close(lbrfile) == ERROR)
X abend("\n\rCan't close library: %s",lbrname);
X lbropen = FALSE;
X if (isambig(name) || indexc(name,' ') != ERROR)
X abend("\n\rBad library name: %s",name);
X if (name[1] == ':' && *name > *drmsg)
X abend("\n\r%s",drmsg);
X strcpy(lbrname,name);
X if (indexc(name,'.') == ERROR)
X strcat(lbrname,".LBR");
X if ((lbrfile = fopen(lbrname,"r")) != NULL)
X {
X printf("\n\rLibrary: %s has ",lbrname);
X readdir();
X }
X else
X return ERROR;
X lbropen = TRUE;
X printf ("%d entries, %d free:\n\r",entries,freeent);
X return OK;
X}
X
X/************************************************
X Return flag saying if the requested number of memory bytes
X are available. Try to make them available if possible.
X*************************************************/
X
XFLAG avail(request)
Xunsigned short request; /* in bytes */
X{
X char *ptr;
X unsigned short *curavail, temp;
X temp = 0;
X
X curavail = &temp; /* Pseudo-static kluge */
X
X if(request < *curavail)
X return TRUE;
X if ((ptr = (char *)sbrk(++request - *curavail)) == (char *)ERROR)
X return FALSE;
X
X /* If this is the first success, initialize pointer */
X if (directory == NULL)
X directory = (dirtype *) ptr;
X
X *curavail = request; /* Modify static for next call */
X return TRUE;
X}
X
X/************************************************/
X/* Read the directory into memory */
X/*************************************************/
X
Xreaddir()
X{
X if (!avail(SECSIZ))
X memerr();
X fseek(lbrfile, 0, FROM_START);
X
X if (
X fread(directory,128,1,lbrfile) != 1
X || entcmp(directory,"\0 ")
X || directory->indx
X || !directory->size
X )
X abend("no directory.");
X if (directory->size > 1)
X {
X if (!avail(SECSIZ * directory->size))
X memerr();
X if (fread(directory+EPS,128, directory->size - 1,lbrfile)
X != directory->size - 1)
X abend("a bad directory");
X }
X
X freeent = entries = EPS * directory->size;
X
X for(
X curentry = directory;
X curentry->status != VIRGIN && freeent;
X ++curentry
X )
X --freeent;
X}
X
X/************************************************
X memory error
X*************************************************/
X
Xmemerr()
X{
X abend("an absurdly huge directory");
X}
X
X/************************************************
X Search string *s for character c. Return offset
X*************************************************/
X
Xshort indexc(s, c)
Xchar *s, c;
X{
X short i;
X for (i = 0; *s; i++)
X if(*s++ == c)
X return i;
X return ERROR;
X}
X
X/************************************************
X Return TRUE if s contains asterisk(s) or question(s)
X*************************************************/
X
Xisambig(s)
Xchar *s;
X{
X if (indexc(s,'*') != ERROR || indexc(s,'?') != ERROR)
X return TRUE;
X return FALSE;
X}
X
X/************************************************
X Terminate program with error message
X*************************************************/
X
Xabend(p1, p2, p3, p4)
X{
X printf(p1, p2, p3, p4);
X puts("\n\r\nFor help, type LDIR alone.");
X exit();
X}
X
X/************************************************
X compare string a to string b ignoring some bits of each
X*************************************************/
Xshort
Xbitcmp(a, b, count, mask)
Xchar *a, *b, mask;
Xshort count;
X{
X short r;
X while(count--)
X if (r = (*a++ & mask) - (*b++ & mask))
X return r;
X return 0;
X}
X
X/************************************************
X form a string in dst from a standard format name in src
X*************************************************/
X
Xformname(dst,src)
Xchar *dst, *src;
X{
X int i,j;
X j = 0;
X
X/* Remove attributes first so compares will work */
X for (i = 1; i < 12; i++)
X src[i] &= 0x7F;
X for (i = 1; i < 9; i++)
X {
X if (src[i] == ' ')
X break;
X dst[j++] = src[i];
X }
X if (src[9] != ' ')
X dst[j++] = '.';
X for (i = 9; i < 12; i++)
X {
X if (src[i] == ' ')
X break;
X dst[j++] = src[i];
X }
X dst[j] = '\0';
X return;
X}
X
X/************************************************
X Compare two directory entries. Note that status is major
X sort field.
X*************************************************/
Xshort
Xentcmp(a,b)
Xchar *a, *b;
X{
X short i, r;
X
X for (i = (1+8+3); i--; a++, b++)
X if ((r = *a - *b) && *b != '?')
X return r;
X return 0;
X}
X
X/************************************************
X List the directory of the current library, and return number
X of free entries
X*************************************************/
X
Xdirlist()
X{
X char name[20];
X short i;
X unsigned del, act;
X
X curentry = directory;
X for ((act = del = 0, i = entries - freeent); --i;)
X {
X if ((++curentry)->status == ACTIVE)
X {
X if(!(act % NWIDE))
X puts("\n\r");
X formname(name, curentry);
X
X switch (sopt)
X {
X case 'S': /* Size in sectors */
X printf("%-12s%5ds ", name, curentry->size);
X break;
X case 'K': /* Size in Kilobytes */
X printf("%-12s%5dk ",name, (curentry->size+7)/8);
X break;
X case 'N': /* Name only. More names per line */
X printf("%-14s",name);
X }
X ++act;
X }
X else
X ++del;
X }
X printf("\n\r Active entries: %u, Deleted: %u, Free: %u, Total: %u.\n\r",
X ++act, del, freeent, entries);
X return --act;
X}
X
X/************************************************
X Process option string (-xx)
X*************************************************/
X
Xprocopt(s)
Xchar *s;
X{
X
X while(*(++s))
X switch (*s)
X {
X case 'S':
X case 'N':
X case 'K':
X case 's':
X case 'n':
X case 'k':
X sopt = toupper(*s);
X break;
X default:
X abend("'%c' is an invalid option",*s);
X }
X}
SHAR_EOF
if test 10133 -ne "`wc -c 'ldir.c'`"
then
echo shar: error transmitting "'ldir.c'" '(should have been 10133 characters)'
fi
echo shar: extracting "'ltype.c'" '(2093 characters)'
if test -f 'ltype.c'
then
echo shar: over-writing existing file "'ltype.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'ltype.c'
X#define VERSION 0
X#define REVISION 0
X#define MOD_DATE "04/18/85"
X
X/* This program will type a member of a LBR file... any member,
X BUT anything other than an ASCII file will produce a screenful
X of garbage.
X
X USE: LTYPE <library> <member>
X*/
X#include <stdio.h>
X#include <sys/file.h>
X
Xchar curdsk, fcb[36];
Xchar fnam[12], libnam[16], dirbuf[128], *dirp;
Xint fd, dirsiz, filsiz;
X
X#define OK 0
X#define ERROR -1
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X printf("\n\rLTYPE vers:%d.%02d %s\n\r\n",
X VERSION,REVISION,MOD_DATE);
X opnlib(argv[1]);
X if (fndmem(argv[2]) == ERROR) erxit("\n\rMember not in LBR file!\n\r");
X printf("\n\rFile present - %d sectors.\n\r",filsiz);
X doit();
X}
X
Xdoit()
X{
X int j;
X int c;
X dirsiz = filsiz;
X do {
X reload();
X for (j=0; j<128; j++){
X if (*dirp == 0x1a) exit();
X putchar(*dirp);
X if(*dirp == 0x0a) putchar(0x0d);
X dirp++;
X }
X }while(dirsiz != 0);
X}
X
Xopnlib(file)
Xchar *file;
X{
X char l, *npnt;
X strcpy(libnam,file);
X fd = open(libnam,O_RDONLY);
X if(fd == -1) erxit("Library file not found.\n");
X}
X
Xfndmem(file)
Xchar *file;
X{
X char dnam[16], fname[36];
X long int floc;
X setfcb(fname,file);
X read(fd,dirbuf,128);
X dirp = dirbuf;
X dirsiz = *(dirp+14);
X dirp += 32;
X do{
X if (*dirp == 255) return(ERROR);
X if (*dirp == 0){
X strcpy(dnam, dirp+1);
X dnam[11]=0;
X if(strcmp(dnam, fname) == 0){
X filsiz = (*(dirp+14)) + ((*(dirp+15)) * 256);
X floc=(*(dirp+12)) + ((*(dirp+13)) * 256);
X lseek(fd,floc *128,0);
X return(OK);
X }
X }
X dirp += 32;
X if(dirp > dirbuf+128) reload();
X } while(dirsiz);
X return(ERROR);
X}
X
Xreload()
X{
X read(fd,dirbuf,128);
X dirp = dirbuf;
X dirsiz--;
X}
X
Xmatchr(st,ch)
Xchar *st,ch;
X{
X int i;
X for(i=0; st[i]; i++){
X if(st[i] == ch) return(i);
X }
X return(0);
X}
X
Xsetfcb(fname,file)
Xchar *fname;
Xchar *file;
X{
X int i,j;
X i = 0; j = 0;
X while (file[j] && file[j] != '.' && i < 8) fname[i++] = file[j++];
X while (i < 8) fname[i++] = ' ';
X if (file[j] == '.') while (i < 11 && file[++j]) fname[i++] = file[j];
X while (i < 11) fname[i++] = ' ';
X fname[11] = 0;
X}
X
Xerxit(strg)
Xchar *strg;
X{
X printf(strg);
X exit();
X}
SHAR_EOF
if test 2093 -ne "`wc -c 'ltype.c'`"
then
echo shar: error transmitting "'ltype.c'" '(should have been 2093 characters)'
fi
# End of shell archive
exit 0
--
Bill Swan {ihnp4|decvax|allegra|...}!uw-beaver!tikal!persci!bill