home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d178
/
ls
/
ls.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-04
|
24KB
|
903 lines
/* --------------------------------------------------------------------- *
LS.C -- an "improved" directory listing utility to replace the
AmigaDOS DIR and LIST commands.
V1.0 August 1986 Written from scratch by Justin V. McCormick.
V2.0 November 1988 Revised for Lattice 5.0 and made 1.3 compatible.
Notice:
This program is placed in the public domain with the understanding
that the author makes no claims or guarantees with regard to its
suitability for any given application, and that the author assumes no
responsibility for damages incurred by its usage. Any resemblance
of this program to any other program, either living or dead, is
purely coincidental.
Feel free to steal this code and make millions of dollars from its sale
or commercial use, but please give credit where credit is due.
Synopsis:
Features adaptive columnar listing, versatile sort options,
UNIX-style pattern matching, recursive subdirectory listing, etc!
Usage:
ls [options] [path1] [path2] ...
Options:
-? Help!
-c Show file comment info, -c implies -l
-d Show directory names only
-f Show filenames only
-l Long verbose listing showing filesizes and dates
-n No sort, just spit them out in the order ExNext() returns
-r Reverse sort direction
-s Sorted by size smallest to largest
-t Sorted by date oldest to newest
-R Recursive descent of subdirectories
All arguments are optional. Default is to give short columnar listing,
sorted alphabetically, using the current directory. Alphabetizing is case
insensitive.
Patterns may be matched in the given names, using the UNIX-style '*'
to wildcard any number of characters, and '?' to wildcard a single
character. If you need to specify a pathname with spaces in it like
"Wombat Soup", you need to put quotes around it. LS can process up to 30
separate pathname patterns in one command line.
Bugs:
Redirecting the shortlist output to PRT: gives undesirable results,
since I am using relative cursor positioning commands to format the
screen output. I thought about using an array to store a virtual
screen, but my primary goals were to keep the size down and display
speed at a maxiumum. Also, LS cannot pattern match devices (like "dh*:")
or support multiple levels of pattern matching (like "dh0:?/L*.info").
This would involve another level of recursion and groking the Device List.
Changes From 1.0 to 2.0:
o Source code prototyped, linted, traced, optimized, tweaked, etc.
o Made resident ("pseudo-pure") by linking with cres.o from LC 5.0.
o High-volume routines recoded in assembly (lssup.a).
o Now handles multiple paths/files on a command line, up to 30.
o New sort flags, including no sort.
o Enhanced wildcards, understands complex *.?*.* expressions now.
o More efficient ExNext() performance, less ram used for recursion.
o SIGBREAKF_CTRL_C signal (Ctrl-C) cleanly aborts at any point now.
o Command line parser handles quoted pathnames now (LC 5.0 benefit).
o Short listing finally auto-adjusts to new console window sizes!
o Pen color escape codes bypassed when redirecting long output.
o Sorting by size or date is also subsorted alphabetically now.
o Long listing shows new 1.3 file attributes, plus comment indicator.
o File dates are now in international format, YY-MM-DD.
o Fixed listings with files datestamped after 99-12-31 (overflow).
o Fixed listings with files datestamped before 78-01-01 (time < 0).
* --------------------------------------------------------------------- */
#include "ls.h"
/* Structure used to hold file info in a linked list */
struct FibEntry
{
struct FibEntry *NextFib;
struct FibEntry *LastFib;
struct FileInfoBlock *Fibp;
};
/* Externs from lssup.a */
/*lint +fva2 */
extern int __stdargs asprintf (char *, char *,...);
/*lint -fva2 */
extern __asm void SortFibs (R_D0 long, R_D1 long, R_A0 struct FibEntry *);
extern __stdargs long iswild (char *);
extern __stdargs long wildmatch (char *, char *);
extern __stdargs char *FibFileDate (struct DateStamp *);
extern __stdargs void GetWinBounds(long *, long *);
/* Local CODE */
struct FibEntry *GetDir (BPTR, struct FileInfoBlock *);
struct FibEntry *AllocFib (void);
void CleanUp (char *, long);
void ColorPen2 (void);
void CursorOff (void);
void CursorOn (void);
void DirIt (BPTR, char *);
void FreeAllFibs (struct FibEntry *);
void FreeFib (struct FibEntry *);
void LListDir (struct FibEntry *);
void LListEntry (struct FileInfoBlock *);
void LongList (long *, long *, struct FibEntry *);
void main (int, char **);
void PagePrompt (long);
void ResetPen (void);
void SListDir (struct FibEntry *);
void TestBreak (void);
void Usage (void);
void WCHR (char *);
void WSTR (char *);
BPTR Out = 0L;
BPTR In = 0L;
BPTR lockp = 0L;
struct FileInfoBlock *GFibp = 0L;
long BREAKFLAG = 0;
long CONSOLE = 0;
long dircount = 0;
long DIRFILEFLAG = 0;
long errstat = 0;
long filecount = 0;
long LISTALL = 0;
long LONGLIST = 0;
long maxnamlen = 0;
long NOSORTFLAG = 0;
long NOTEFLAG = 0;
long PATHNAMED = 0;
long REVFLAG = 0;
long sortkey = 0;
long WILDCARD = 0;
long CurWinRows = 20L;
long CurWinCols = 77L;
char filename[160];
char pattern[160];
char workstr[160];
static char Author[] = "\23333mLS 2.0\2330m by Justin V. McCormick 1988";
static char usage[] = "\nUsage: ls [-cdflnrstR] [path1] [path2] ...\n";
/* -------------------------------------------------------------------- */
void main (argc, argv)
int argc;
char **argv;
{
struct Process *procp;
long cnt, i;
if (argc == 0) /* son of Workbench -- no go! */
exit (0);
/* Grab FileHandles for input and output to console (or redirection file) */
In = Input ();
Out = Output ();
CONSOLE = (IsInteractive (Out) == 0L) ? 0L : 1L; /* Is this console output? */
/* Allocate a global FileInfoBlock for ExNext() */
if ( (GFibp = (struct FileInfoBlock *)AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC | MEMF_CLEAR)) == 0L)
CleanUp("No RAM?", 103L);
/* Parse command line arguments <ugh> */
cnt = 1;
if (argc >= 2)
{
if (argv[1][0] == '-')
{
cnt++;
for (i = strlen(argv[1]) - 1; i > 0; i--)
{
switch (argv[1][i])
{
case 'c':
LONGLIST = 1;
NOTEFLAG = 1;
break;
case 'd':
DIRFILEFLAG |= 1;
break;
case 'f':
DIRFILEFLAG |= 2;
break;
case 'l':
LONGLIST = 1;
break;
case 'n':
NOSORTFLAG = 1;
break;
case 'r':
REVFLAG = 1;
break;
case 's':
sortkey = 1;
break;
case 't':
sortkey = 2;
break;
case 'R':
LISTALL = 1;
break;
case '?':
Usage ();
break;
default:
(void) asprintf (workstr, "Unknown option \'%c\'\n", argv[1][i]);
WSTR (workstr);
Usage ();
break;
}
}
}
}
/* Clean up the state flags */
if ( (argc - cnt) > 1)
LISTALL |= 2;
if (DIRFILEFLAG == 0)
DIRFILEFLAG = 3;
/* Loop through the remaining args now */
do
{
PATHNAMED = 0;
if (cnt < argc)
{
(void) stpcpy (pattern, argv[cnt]);
PATHNAMED = 1;
}
if (PATHNAMED) /* If user specified a pathname */
{
WILDCARD = iswild (pattern); /* check for wildcards */
if (WILDCARD) /* If wildcards, separate */
{ /* pattern from pathname */
for (i = (strlen (pattern) - 1); i >= 0; i--)
{
if (pattern[i] == '/' || pattern[i] == ':')
{
(void) strncpy (filename, pattern, (UWORD) (i + 1));
filename[i + 2] = (BYTE) 0;
(void) stpcpy (workstr, &pattern[i + 1]);
(void) stpcpy (pattern, workstr);
break;
}
}
/* Disallow wildcards in pathname */
if (iswild (filename))
CleanUp ("Sorry, can't pattern match paths", 5L);
}
else /* No wildcards, use filename as is */
{
(void) stpcpy (filename, pattern);
}
/* If the user specified a pathname, try to grab a FileLock on it */
/* Discard trailing slash if silly Joe User put one there */
if (filename[1] != 0 && filename[strlen (filename) - 1] == '/')
filename[strlen (filename) - 1] = (BYTE) 0;
lockp = Lock (filename, ACCESS_READ);
if (!lockp) /* Can't Lock it! */
{
errstat = IoErr ();
(void) strcat (filename, " not found");
CleanUp (filename, (long)errstat);
}
}
else
{
/*
* If no filename was specified, steal Lock on current directory from
* CLI process task info. We durn well better get something useful back;
* we don't do any error checking on the stolen Lock.
*/
procp = (struct Process *) FindTask (0L);
lockp = procp->pr_CurrentDir;
filename[0] = 0; /* Tell DirIt() to use current dir */
}
/* Get the directory for this path, display it */
DirIt (lockp, filename);
/* Release the lock, bump our arg counter */
if (lockp != 0 && PATHNAMED != 0)
UnLock (lockp);
lockp = 0L;
cnt++;
if (cnt < argc)
WCHR("\n");
} while (cnt < argc && BREAKFLAG == 0);
CleanUp ("", 0L);
}
/* -------------------------------------------------------------------- */
/* Deallocate and close everything */
/* -------------------------------------------------------------------- */
void CleanUp (exit_msg, exit_status)
char *exit_msg;
long exit_status;
{
if (lockp && PATHNAMED)
UnLock (lockp);
if (GFibp != 0L)
FreeMem(GFibp, (long)sizeof(struct FileInfoBlock));
if (exit_status)
{
(void) asprintf (workstr, "ls: %s, Error #%ld\n", exit_msg, exit_status);
WSTR (workstr);
}
exit ((int) exit_status);
}
/* -------------------------------------------------------------------- */
void DirIt (lockp, dirname)
BPTR lockp;
char *dirname;
{
BPTR tlockp;
struct FibEntry *fibheadp;
struct FibEntry *tfibp;
char *subdir;
long strsize;
/* Try to fill FileInfoBlock, bomb if not readable for some reason */
if (!Examine (lockp, GFibp))
{
(void) asprintf (workstr, "Can't examine file or directory\n");
WSTR (workstr);
return;
}
/* Put directory header if this is a recursive listing */
if (dirname[0] && LISTALL > 0)
{
if (CONSOLE != 0)
(void)asprintf(workstr, "\23330;41m %s \2330m\n", dirname);
else
(void)asprintf(workstr, "%s\n", dirname);
WSTR(workstr);
}
/* If this is a single file list it verbosely */
if (GFibp->fib_EntryType < 0 && (DIRFILEFLAG & 2) != 0)
{
LListEntry (GFibp);
}
else
{
/* Otherwise do a directory */
/* Allocate and initialize a FibEntry head node */
if ( (fibheadp = GetDir (lockp, GFibp)) != 0L && BREAKFLAG == 0)
{
if (NOSORTFLAG == 0)
SortFibs ((long)sortkey, REVFLAG, fibheadp);
if (LONGLIST == 0)
SListDir (fibheadp);
else
LListDir (fibheadp);
if ( (LISTALL & 1) != 0)
{
tfibp = fibheadp;
do
{
if (tfibp->Fibp->fib_EntryType > 0)
{
strsize = (strlen (dirname) + strlen (tfibp->Fibp->fib_FileName) + 2);
subdir = (char *) AllocMem ((LONG)strsize, 0L);
if (strlen (dirname) != 0)
{
(void) stpcpy (subdir, dirname);
if (dirname[strlen (dirname) - 1] != ':')
(void) strcat (subdir, "/");
}
(void) strcat (subdir, tfibp->Fibp->fib_FileName);
tlockp = Lock (subdir, ACCESS_READ);
if (tlockp == 0L)
{
WSTR (subdir);
WSTR (" -- can't lock it!\n");
break;
}
else
{
WCHR ("\n"); /* Put a blank line between directories */
DirIt (tlockp, subdir);
UnLock (tlockp);
FreeMem (subdir, (LONG)strsize);
}
}
tfibp = tfibp->NextFib;
} while (tfibp != fibheadp && BREAKFLAG == 0);
}
}
/* Clean up */
FreeAllFibs (fibheadp);
}
}
/* -------------------------------------------------------------------- */
/* Allocate and fill a linked list of FileInfoBlocks */
/* -------------------------------------------------------------------- */
struct FibEntry *GetDir (lockp, fibp)
BPTR lockp;
struct FileInfoBlock *fibp;
{
long nextstat;
long tempnamlen;
struct FibEntry *tfibp;
struct FibEntry *headfib;
maxnamlen = dircount = filecount = 0L;
headfib = 0L;
do
{
TestBreak();
if (BREAKFLAG != 0)
return(headfib);
nextstat = ExNext (lockp, fibp);
if (nextstat != 0) /* We got something */
{
/* See if it matches our pattern */
if (!WILDCARD || wildmatch (fibp->fib_FileName, pattern))
{
/* Bump count of files or directories */
if (fibp->fib_EntryType > 0)
{
if ((DIRFILEFLAG & 1) != 0)
dircount++;
else
goto ALLOCFIB;
}
else
{
if ((DIRFILEFLAG & 2) != 0)
filecount++;
else
continue;
}
/* See if this is the longest filename for later use in listing */
tempnamlen = strlen (fibp->fib_FileName);
if (tempnamlen > maxnamlen)
maxnamlen = tempnamlen;
ALLOCFIB:
/* Allocate another FibEntry to put the info in */
if (headfib == 0L)
{
headfib = AllocFib();
if (headfib == 0L)
return(headfib);
headfib->NextFib = headfib;
headfib->LastFib = headfib;
*(headfib->Fibp) = *(fibp);
tfibp = headfib;
}
else
{
tfibp->NextFib = AllocFib ();
if (tfibp->NextFib == 0L)
return(0L);
/* Copy FIB contents to next entry for ExNext to work with */
*(tfibp->NextFib->Fibp) = *(fibp);
/* Link it into the list */
tfibp->NextFib->LastFib = tfibp;
tfibp = tfibp->NextFib;
tfibp->NextFib = headfib;
}
}
}
} while (nextstat);
/* Return TRUE if entries found, else print message and return FALSE */
if ( (dircount + filecount) != 0)
{
return (headfib);
}
else
{
if (WILDCARD == 0 && DIRFILEFLAG == 3)
WSTR ("Volume or directory is empty.\n");
else
WSTR ("No match.\n");
return (0L);
}
}
/* -------------------------------------------------------------------- */
/* List a FibEntry list in a compact fashion */
/* -------------------------------------------------------------------- */
void SListDir (fibheadp)
struct FibEntry *fibheadp;
{
struct FibEntry *tfibp;
long tabsize;
long maxtab;
long totrows;
long maxwinrow;
long colcnt;
long rowcnt;
long tabcnt;
long pagecnt = 1;
CursorOff (); /* Turn the cursor off since it will blink anyway */
GetWinBounds(&CurWinCols, &CurWinRows);
tfibp = fibheadp;
tabcnt = rowcnt = colcnt = 0;
tabsize = maxnamlen + 2;
if (CurWinCols < tabsize)
maxtab = 1;
else
maxtab = CurWinCols / tabsize;
maxwinrow = CurWinRows - 3;
if (maxwinrow <= 0)
maxwinrow = 1;
totrows = (dircount + filecount) / maxtab;
if ((dircount + filecount) % maxtab != 0)
totrows++;
do
{
if (tfibp->Fibp->fib_EntryType > 0)
{
if ( (DIRFILEFLAG & 1) == 0)
goto GETNEXTFIB;
else
ColorPen2 ();
}
if (tabcnt)
(void) asprintf (workstr, "\233%ldC", (long)tabcnt);
else
workstr[0] = (BYTE) 0;
(void) strcat (workstr, tfibp->Fibp->fib_FileName);
(void) strcat (workstr, "\n");
WSTR (workstr);
if (tfibp->Fibp->fib_EntryType > 0)
ResetPen ();
rowcnt++;
if (rowcnt == maxwinrow || rowcnt == totrows)
{
colcnt++; /* Start a new column */
/* Check to see if we have used the last column up and are about to run
* off the screen entirely. If so, give the user a chance to read it first.
*/
if (colcnt == maxtab && rowcnt == maxwinrow && CONSOLE != 0)
{
if (maxwinrow > 1)
{
++pagecnt; /* Advance page number count */
PagePrompt (pagecnt); /* Print it, wait for user */
}
totrows -= maxwinrow;
colcnt = tabcnt = rowcnt = 0L;
}
else /* Just move over one row and back up to the top */
{
(void) asprintf (workstr, "\233%ldA", (long)rowcnt);
WSTR (workstr);
tabcnt += tabsize;
rowcnt = 0L;
}
}
GETNEXTFIB:
tfibp = tfibp->NextFib;
} while (tfibp != fibheadp);
if (totrows - rowcnt > 0) /* Cursor down till level with */
{ /* lowest line on screen */
(void) asprintf (workstr, "\233%ldE", (long)(totrows - rowcnt));
WSTR (workstr);
}
CursorOn ();
}
/* -------------------------------------------------------------------- */
/* Reset character color to default Pen1 colors */
/* -------------------------------------------------------------------- */
void ResetPen ()
{
if (CONSOLE != 0)
WSTR ("\2330m");
}
/* -------------------------------------------------------------------- */
/* Turn the cursor on */
/* -------------------------------------------------------------------- */
void CursorOn ()
{
if (CONSOLE != 0)
WSTR ("\233 p");
}
/* -------------------------------------------------------------------- */
/* Turn the cursor off for faster text output */
/* -------------------------------------------------------------------- */
void CursorOff ()
{
if (CONSOLE != 0)
WSTR ("\2330 p");
}
/* -------------------------------------------------------------------- */
/* Make Pen2 <usually yellow/orange> the current charcter color */
/* -------------------------------------------------------------------- */
void ColorPen2 ()
{
if (CONSOLE != 0)
WSTR ("\23333m");
}
/* -------------------------------------------------------------------- */
/* Prompt the user to hit return, wait till return is hit */
/* -------------------------------------------------------------------- */
void PagePrompt (page)
long page;
{
WSTR ("\2337m -- MORE -- Press Return: \2330m");
(void) Read (In, workstr, 1L);
(void) asprintf (workstr, "\233F\233K\2334;33mPage %ld:\2330m\n", (long)page);
WSTR (workstr);
}
/* -------------------------------------------------------------------- */
/* List a directory in a verbose informative manner */
/* -------------------------------------------------------------------- */
void LListDir (fibheadp)
struct FibEntry *fibheadp;
{
long totblocks = 0L;
long totbytes = 0L;
CursorOff ();
LongList (&totblocks, &totbytes, fibheadp);
(void) asprintf (workstr, "Dirs:%-3ld Files:%-4ld Blocks:%-5ld Bytes:%-8ld\n",
(long)dircount, (long)filecount, totblocks, totbytes);
WSTR (workstr);
CursorOn ();
}
/* -------------------------------------------------------------------- */
void LongList (totblocks, totbytes, fibheadp)
long *totblocks, *totbytes;
struct FibEntry *fibheadp;
{
struct FibEntry *tfibp;
tfibp = fibheadp;
do
{
LListEntry (tfibp->Fibp);
if (tfibp->Fibp->fib_EntryType < 0)
{
*totblocks += tfibp->Fibp->fib_NumBlocks;
*totbytes += tfibp->Fibp->fib_Size;
}
tfibp = tfibp->NextFib;
} while (tfibp != fibheadp);
}
/* -------------------------------------------------------------------- */
/* Verbosely list a particular FibEntry */
/* -------------------------------------------------------------------- */
void LListEntry (fib)
struct FileInfoBlock *fib;
{
long i, pmodes;
char *cp1;
char entry[160];
pmodes = fib->fib_Protection & 0xff;
cp1 = stpcpy (entry, "chsparwed ");
for (i = 0; i < 4; i++)
{
if ((pmodes & (1 << i)) != 0)
entry[8 - i] = '-';
}
for (; i < 8; i++)
{
if ((pmodes & (1 << i)) == 0)
entry[8 - i] = '-';
}
if (fib->fib_Comment[0] == 0)
entry[0] = '-';
cp1 = stpcpy (cp1, FibFileDate (&fib->fib_Date));
if (fib->fib_EntryType > 0)
{
if ( (DIRFILEFLAG & 1) == 0)
return;
if (CONSOLE)
cp1 = stpcpy (cp1, "\23333m");
cp1 = stpcpy (cp1, " Directory ");
if (CONSOLE)
cp1 = strcat (cp1, "\2330m");
}
else
(void) asprintf (&entry[27], " %4ld %8ld ", fib->fib_NumBlocks, fib->fib_Size);
(void)strcat(entry, fib->fib_FileName);
(void)strcat(cp1, "\n");
WSTR (entry);
if (NOTEFLAG != 0 && fib->fib_Comment[0] != 0)
{
if (CONSOLE)
(void)asprintf(cp1, "\23333m/* %s */\2330m\n", fib->fib_Comment);
else
(void)asprintf(cp1, "/* %s */\n", fib->fib_Comment);
WSTR (workstr);
}
}
#ifdef NOASM
/* -------------------------------------------------------------------- */
/* Calculate date based on DateStamp structure, return a string pointer */
/* -------------------------------------------------------------------- */
char *CalcDate (fib)
struct FileInfoBlock *fib;
{
static long days[12] =
{
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static char *months[12] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
char datestr[25];
long i, mdays;
long day, hour;
long minute, sec;
long ldays;
long year;
ldays = 1461L;
year = 78L;
day = fib->fib_Date.ds_Days;
minute = fib->fib_Date.ds_Minute;
sec = fib->fib_Date.ds_Tick / 50L;
year += (day / ldays) * 4L;
day %= ldays;
while (day)
{
mdays = 365;
if ((year & 3) == 0)
mdays++;
if (day < mdays)
break;
day -= mdays;
year++;
}
for (i = 0L, day++; i < 12; i++)
{
mdays = days[i];
if (i == 1 && (year & 3) == 0)
mdays++;
if (day <= mdays)
break;
day -= mdays;
}
hour = minute / 60;
minute -= hour * 60;
(void) asprintf (datestr, "%02ld-%s-%02ld %02ld:%02ld:%02ld ", day, (long)months[i], year, hour, minute, sec);
return (datestr);
}
#endif
/* -------------------------------------------------------------------- */
/* Use AmigaDos to put a string on the stdout */
/* -------------------------------------------------------------------- */
void WSTR (tstring)
char *tstring;
{
(void) Write (Out, tstring, (long) strlen (tstring));
}
/* -------------------------------------------------------------------- */
/* Use AmigaDos to put a character on the stdout */
/* -------------------------------------------------------------------- */
void WCHR (ch)
char *ch;
{
(void) Write (Out, ch, 1L);
}
/* -------------------------------------------------------------------- */
/* Check to see if the user hit ^C */
/* -------------------------------------------------------------------- */
void TestBreak ()
{
unsigned long oldsig;
oldsig = SetSignal (0L, SIGBREAKF_CTRL_C);
if ( (oldsig & SIGBREAKF_CTRL_C) != 0L)
{
WSTR ("\2330m\233 p**BREAK\n");
BREAKFLAG = 1;
}
}
/* -------------------------------------------------------------------- */
/* Explain how to use */
/* -------------------------------------------------------------------- */
void Usage ()
{
WSTR (Author);
WSTR (usage);
WSTR (" c > Show comments\n");
WSTR (" d > Dirs only\n");
WSTR (" f > Files only\n");
WSTR (" l > Long listing\n");
WSTR (" n > No sort\n");
WSTR (" r > Reverse sort\n");
WSTR (" s > Sort by size\n");
WSTR (" t > Sort by date\n");
WSTR (" R > Recursive listing\n");
CleanUp ("", 0L);
}
/* -------------------------------------------------------------------- */
/* Allocate a FibEntry structure and associated FileInfoBlock */
/* -------------------------------------------------------------------- */
struct FibEntry *AllocFib ()
{
struct FibEntry *tfibp;
tfibp = (struct FibEntry *) AllocMem \
((long)( sizeof (struct FibEntry) + sizeof(struct FileInfoBlock) ), 0L);
if (tfibp != 0L)
{
tfibp->Fibp = (struct FileInfoBlock *)((ULONG)tfibp + sizeof(struct FibEntry));
}
else
BREAKFLAG = 1;
return (tfibp);
}
/* -------------------------------------------------------------------- */
/* Free up memory allocated to a linked list of FibEntrys */
/* -------------------------------------------------------------------- */
void FreeAllFibs (fibheadp)
struct FibEntry *fibheadp;
{
struct FibEntry *fibp;
struct FibEntry *tfibp;
if (fibheadp != 0)
{
fibp = fibheadp;
do
{
tfibp = fibp->NextFib;
FreeFib (fibp);
fibp = tfibp;
} while (tfibp != fibheadp);
}
}
/* -------------------------------------------------------------------- */
/* Deallocate a single FibEntry structure */
/* -------------------------------------------------------------------- */
void FreeFib (fibp)
struct FibEntry *fibp;
{
if (fibp != 0L)
FreeMem (fibp, (long)(sizeof (struct FibEntry) + sizeof(struct FileInfoBlock)));
}