home *** CD-ROM | disk | FTP | other *** search
- /* --------------------------------- -------
- * |\ | | | | | |.| | \| |/ /|\ |||||||
- * | | | |/ | |\ |/ |/| |\ |/ | ? ---+--- =<
- * | | | | | | | | | | | \qqqqqqqqq/
- * --------------------------------- ~~~~~~~~~~~~~~~~
- * DirTree - Prints sub-directory trees
- * Copyright (C) 1992, 1993 Torsten Poulin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * The author can be contacted by s-mail at
- * Torsten Poulin
- * Banebrinken 99, 2, 77
- * DK-2400 Copenhagen NV
- * DENMARK
- *
- * Created 23-Feb-92 (Version 1)
- * $Id: DirTree.c,v 37.5 93/03/01 12:52:58 Torsten Rel $
- * $Log: DirTree.c,v $
- * Revision 37.5 93/03/01 12:52:58 Torsten
- * Changed all occurrences of "struct DosBase *" to "struct DosLibrary *"
- *
- * Revision 37.4 93/02/17 22:33:59 Torsten
- * Fixed Enforcer problems when dealing with the no directories
- * specified case.
- *
- * Revision 37.3 93/02/17 09:12:25 Torsten
- * DIR/M is not a required argument anymore.
- * Is now aware of links, but will not follow them.
- * It used to think that softlinks (fib_DirEntryType == ST_SOFTLINK)
- * were directories that could be entered.
- * Changed the header text a bit.
- * Does not AllocMem() space for filename in listnodes anymore.
- * Now checks whether AllocDosObject() succeeds.
- *
- * Revision 37.2 93/02/12 15:15:49 Torsten
- * Now responds to Ctrl-C!!! Major improvement!!!
- * New switch: FILES.
- *
- */
-
- /*
- * The bit-map code in this program was picked up from Dr. Dobb's
- * I think, but I don't remember which volume ;-(
- *
- * Define LOCKALL to ensure that directories being examined
- * don't disappear before we're done with them.
- * The disadvantage is that we use more memory.
- */
- #define LOCKALL
-
-
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <dos/dostags.h>
- #include <dos/datetime.h>
- #include <dos/dosasl.h>
- #include <string.h>
-
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- #include "dirtree_rev.h"
-
- /* my include files are for V36, so ... */
- #pragma libcall UtilityBase Stricmp A2 9802
- LONG Stricmp(char *, char *);
-
- #define PROGNAME "DirTree"
- #define USERBREAK (-1)
- #define BAR "| "
- #define ELL "`---"
- #define TEE "+---"
-
- struct nameList {
- struct nameList *next;
- char name[108]; /* just to be safe... */
- LONG type;
- #ifdef LOCKALL
- BPTR lock;
- #endif
- };
-
- typedef struct {
- struct Library *SysBase;
- struct DosLibrary *DOSBase;
- struct Library *UtilityBase;
-
- BOOL nohead;
- BOOL files;
- char Map[64 / 8];
- } Global;
-
- char const versionID[] = VERSTAG;
- char const copyright[] = "$COPYRIGHT:©1992,1993 Torsten Poulin$";
-
- static VOID setbit(Global *global, LONG c, LONG val);
- static VOID print_bars(Global *global, LONG depth, LONG terminate);
- static LONG printdtree(Global *global, UBYTE *dname, LONG others);
- LONG dirtree(Global *global, char *dirname);
-
-
- LONG entrypoint(VOID)
- {
- struct Library *SysBase;
- struct DosLibrary *DOSBase;
- struct Library *UtilityBase;
- Global *global;
-
- struct RDArgs *args;
- LONG arg[3];
- LONG rc = RETURN_OK;
- UBYTE **dir;
-
- arg[0] = arg[1] = arg[2] = 0L;
-
- SysBase = *(struct Library **) 4L;
-
- if (!(global = AllocMem(sizeof(Global), MEMF_PUBLIC | MEMF_CLEAR)))
- return RETURN_FAIL;
-
- global->SysBase = SysBase;
- if (!(global->DOSBase = DOSBase = (struct DosLibrary *)
- OpenLibrary("dos.library", 37L)))
- {
- rc = RETURN_FAIL;
- goto noDOS;
- }
- if (!(global->UtilityBase = UtilityBase =
- OpenLibrary("utility.library", 37L)))
- {
- rc = RETURN_FAIL;
- goto noUtility;
- }
-
- if (args = ReadArgs("DIR/M,NOHEAD/S,FILES/S", arg, NULL))
- {
- global->nohead = (BOOL) arg[1];
- global->files = (BOOL) arg[2];
- dir = (UBYTE **) *arg;
- if (dir)
- for (; *dir && rc == RETURN_OK; dir++)
- rc = dirtree(global, *dir);
- else
- rc = dirtree(global, "");
- FreeArgs(args);
- }
- else
- {
- LONG err = IoErr();
- PrintFault(err, PROGNAME);
- rc = RETURN_ERROR;
- }
-
- CloseLibrary(UtilityBase);
- noUtility:
- CloseLibrary((struct Library *) DOSBase);
- noDOS:
- FreeMem(global, sizeof(Global));
- return rc;
- }
-
-
- #define testbit(x) ( global->Map[x >> 3] & (1 << (x & 0x07)) )
-
- static VOID setbit(Global *global, LONG c, LONG val)
- {
- if (val)
- global->Map[c >> 3] |= 1 << (c & 0x07);
- else
- global->Map[c >> 3] &= ~(1 << (c & 0x07));
- }
-
-
- static VOID print_bars(Global *global, LONG depth, LONG terminate)
- {
- struct DosLibrary *DOSBase = global->DOSBase;
- LONG i;
-
- for (i = 0; i < depth - 1; i++)
- PutStr(testbit(i) ? BAR : " ");
-
- if (terminate)
- PutStr("\n");
- }
-
-
- static LONG printdtree(Global *global, UBYTE *dname, LONG others)
- {
- struct Library *SysBase = global->SysBase;
- struct DosLibrary *DOSBase = global->DOSBase;
- struct Library *UtilityBase = global->UtilityBase;
-
- struct FileInfoBlock *m;
- BPTR lock, oldlock;
- static LONG depth = -1;
- LONG count = 0;
- LONG rc = RETURN_OK;
- struct nameList *list, *p;
- struct nameList *newnode;
- LONG type;
- BOOL OutOfMemory = FALSE;
- BOOL UserBreak = FALSE;
-
- list = NULL;
-
- if (!(m = AllocDosObject(DOS_FIB, NULL)))
- {
- PrintFault(ERROR_NO_FREE_STORE, PROGNAME);
- return RETURN_FAIL;
- }
-
- if (lock = Lock(dname, SHARED_LOCK))
- {
- oldlock = CurrentDir(lock);
- if (Examine(lock, m))
- {
- type = m->fib_DirEntryType;
- if (type < 0 || type == ST_SOFTLINK)
- {
- PrintFault(ERROR_OBJECT_WRONG_TYPE, dname);
- CurrentDir(oldlock);
- UnLock(lock);
- FreeDosObject(DOS_FIB, m);
- return RETURN_WARN;
- }
-
- if (++depth)
- {
- print_bars(global, depth, 0);
- PutStr(others ? TEE : ELL);
- }
- PutStr(m->fib_FileName); /* dir name */
- if (global->files)
- PutStr(" (dir)");
- PutStr("\n");
-
- while (ExNext(lock, m))
- {
- if (UserBreak = (BOOL) CheckSignal(SIGBREAKF_CTRL_C))
- break;
-
- type = m->fib_DirEntryType;
- if (type < 0 && !global->files)
- continue;
-
- /* Store the directory name */
- if (!(newnode = AllocMem(sizeof(struct nameList),
- MEMF_PUBLIC)))
- {
- PrintFault(ERROR_NO_FREE_STORE, PROGNAME);
- rc = RETURN_FAIL;
- OutOfMemory = TRUE;
- break;
- }
- strcpy(newnode->name, m->fib_FileName);
- newnode->type = type;
- #ifdef LOCKALL
- newnode->lock = Lock(m->fib_FileName, SHARED_LOCK);
- #endif
- /* Insert */
- newnode->next = NULL;
-
- if (list == NULL) /* insert into empty list */
- list = newnode;
- else
- {
- /* inserting into nonempty list */
- p = list;
-
- if (Stricmp(m->fib_FileName, p->name) < 0)
- {
- /* insert before first node */
- newnode->next = list;
- list = newnode;
- }
- else
- {
- /* general case */
- for (; p->next; p = p->next)
- if (Stricmp(m->fib_FileName, p->next->name) < 0)
- break;
- newnode->next = p->next;
- p->next = newnode;
- }
- }
- ++count;
- }
- }
-
- /* Traverse the list and free up memory */
- for (p = list; p; )
- {
- struct nameList *remember;
-
- remember = p;
- if (!OutOfMemory && !UserBreak)
- {
- if (p->type >= 0 && p->type != ST_LINKDIR && p->type != ST_SOFTLINK)
- {
- --count;
- setbit(global, depth, count);
- rc = printdtree(global, p->name, count);
- if (rc == USERBREAK)
- UserBreak = TRUE;
- if (rc == RETURN_FAIL)
- OutOfMemory = TRUE;
- }
- else if (global->files || p->type == ST_LINKDIR)
- {
- --count;
- print_bars(global, depth + 1, 0);
- PutStr(count ? TEE : ELL);
- PutStr(p->name);
- switch (p->type)
- {
- case ST_SOFTLINK:
- PutStr(" <sl>");
- break;
- case ST_LINKDIR:
- PutStr(" (dir)");
- /* fall through */
- case ST_LINKFILE:
- PutStr(" <hl>");
- }
- PutStr("\n");
- }
- }
- p = p->next;
- #ifdef LOCKALL
- UnLock(remember->lock);
- #endif
- FreeMem(remember, sizeof(struct nameList));
- }
- CurrentDir(oldlock);
- UnLock(lock);
- }
- else
- {
- LONG err = IoErr();
- PrintFault(err, dname);
- rc = RETURN_ERROR;
- }
- if (!others)
- print_bars(global, depth, 1);
- --depth;
-
- FreeDosObject(DOS_FIB, m);
- if (UserBreak)
- rc = USERBREAK;
- if (OutOfMemory)
- rc = RETURN_FAIL;
- return rc;
- }
-
-
- LONG dirtree(Global *global, char *dirname)
- {
- struct DosLibrary *DOSBase = global->DOSBase;
- LONG rc;
- struct DateTime dt;
- char day[LEN_DATSTRING], date[LEN_DATSTRING];
-
- if (!global->nohead)
- {
- DateStamp(&dt.dat_Stamp);
- dt.dat_Format = FORMAT_DOS;
- dt.dat_Flags = NULL;
- dt.dat_StrDay = day;
- dt.dat_StrDate = date;
- dt.dat_StrTime = NULL;
- DateToStr(&dt);
-
- PutStr("Directory tree \"");
- PutStr(dirname);
- PutStr("\" on ");
- PutStr(day);
- PutStr(" ");
- PutStr(date);
- PutStr("\n\n");
- }
- if ((rc = printdtree(global, dirname, 0)) == USERBREAK)
- {
- PrintFault(ERROR_BREAK, NULL);
- rc = RETURN_WARN;
- }
- return rc;
- }
-