home *** CD-ROM | disk | FTP | other *** search
- /* --------------------------------------------------------------------- *
- 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.
- V2.1 December 1988 Minor size reduction, fixed a few bugs from 2.0.
-
- 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 borrow 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).
-
- Changes From 2.0 to 2.1
-
- o Fixed the show comment feature, a last minute bug in 2.0.
- o Fixed the "Unknown option ''" message problem.
- o Optimized the assembly branches, reduced code size another few bytes.
-
- * --------------------------------------------------------------------- */
-
- /* Don't use __builtin for a minor savings in size */
- #define strlen strlen
-
- /* Pass things using registers */
- #define _PARM __regargs
-
- #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 void __stdargs SortFibs (long, long, struct FibEntry *);
- extern long __stdargs iswild (char *);
- extern long __stdargs wildmatch (char *, char *);
- extern char *__stdargs FibFileDate (struct DateStamp *);
- extern void __stdargs GetWinBounds (long *, long *);
-
-
- /* Local CODE */
- struct FibEntry *GetDir (struct FileLock *, struct FileInfoBlock *);
- struct FibEntry *AllocFib (void);
- void CleanUp (char *, long);
- void ColorPen2 (void);
- void CursorOff (void);
- void CursorOn (void);
- void _PARM DirIt (struct FileLock *, char *);
- void _PARM FreeAllFibs (struct FibEntry *);
- void _PARM FreeFib (struct FibEntry *);
- void _PARM LListDir (struct FibEntry *);
- void _PARM LListEntry (struct FileInfoBlock *);
- void _PARM LongList (long *, long *, struct FibEntry *);
- void main (int, char **);
- void _PARM PagePrompt (long);
- void ResetPen (void);
- void _PARM SListDir (struct FibEntry *);
- void TestBreak (void);
- void Usage (void);
- void _PARM WCHR (char *);
- void _PARM WSTR (char *);
-
- struct FileHandle *Out = 0L;
- struct FileHandle *In = 0L;
- struct FileLock *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.1\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:
- pattern[0] = argv[1][i];
- pattern[1] = 0;
- (void) asprintf (workstr, "Unknown option \'%s\'\n", pattern);
- 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 = (struct FileLock *)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 _PARM DirIt (lockp, dirname)
- struct FileLock *lockp;
- char *dirname;
- {
- struct FileLock *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)
- struct FileLock *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 _PARM 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 _PARM 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 _PARM 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 _PARM 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 _PARM 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(entry, "\23333m/* %s */\2330m\n", fib->fib_Comment);
- else
- (void)asprintf(entry, "/* %s */\n", fib->fib_Comment);
- WSTR (entry);
- }
- }
-
- #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 _PARM WSTR (tstring)
- char *tstring;
- {
- (void) Write (Out, tstring, (long) strlen (tstring));
- }
-
- /* -------------------------------------------------------------------- */
- /* Use AmigaDos to put a character on the stdout */
- /* -------------------------------------------------------------------- */
- void _PARM 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 _PARM 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 _PARM FreeFib (fibp)
- struct FibEntry *fibp;
- {
- if (fibp != 0L)
- FreeMem (fibp, (long)(sizeof (struct FibEntry) + sizeof(struct FileInfoBlock)));
- }
-
-