home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
326.lha
/
ARPTools
/
src
/
L.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-27
|
11KB
|
448 lines
/*
L - Display files and directories in columns.
Original effort by Fabio Rossetti.
(c) 1989 by Fabio Rossetti
To compile under Lattice C v5.0x use:
lc -O -v -cus l
blink lib:cres.o l.o to l lib lib:a.lib lib:lc.lib sd nd
*/
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <devices/console.h>
#include <devices/conunit.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/arpbase.h>
#include <intuition/intuitionbase.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <arpfunctions.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
/* command line arguments */
#define PAT 0
#define CD 1
#define NOCOL 2
#define NARGS 3 /* their # */
/* */
/* global */
/* */
struct ArpBase *ArpBase;
struct IntuitionBase *IntuitionBase;
struct Window *CliWin; /* pointer to console window */
struct Process *Pr;
/* line arguments stuff, must be accessed by several functions */
LONG argc;
STRPTR argv[NARGS];
/* general purpose string buffers */
TEXT Bf[256]="\0";
TEXT Buf[256]="\0";
/* general purpose lock pointer */
BPTR Lck;
struct FileInfoBlock *Fib;
TEXT *Path;
/* this is exec stuff for GetWin, to be kept global for Cleanup() */
struct MsgPort iorp = {
{0, 0, NT_MSGPORT, 0, 0}, 0,
-1, /* initialize signal to -1 */
0,
/* start with empty list */
{&iorp.mp_MsgList.lh_Tail, 0, &iorp.mp_MsgList.lh_Head, 0, 0}
};
struct IOStdReq ior = {
{{0, 0, 0, 0, 0}, &iorp, 0},
0 /* device is zero */
};
/* pointer to ordered list of files to be displayed */
struct DirectoryEntry *FileList = NULL;
/* Stamptostr() stuff, kept global for future expansions and v5.0 quirks */
struct DateTime D =
{
0L,0L,0L,
FORMAT_DOS,
NULL,
NULL,
NULL,
NULL };
TEXT Date[LEN_DATSTRING],
Time[LEN_DATSTRING],
Day[LEN_DATSTRING];
VOID MemCleanup()
{
}
/* general shutdown routine*/
VOID Cleanup(code,retcode,filelist,anchor)
LONG code;
LONG retcode;
struct DirectoryEntry *filelist;
struct AnchorPath *anchor;
{
if (ior.io_Device != 0) {
if (iorp.mp_SigBit != -1) {
FreeSignal(iorp.mp_SigBit);
}
CloseDevice(&ior);
}
CloseLibrary((struct Library*)ArpBase);
if (anchor) FreeAnchorChain(anchor);
if (filelist) FreeDAList(filelist);
Pr->pr_Result2=retcode;
exit(code);
}
/* bulletproofly obtain a pointer to the CLI window sending a ACTION_DISK_INFO
packet to the console process and looking into InfoData */
struct Window *GetWin()
{
struct MsgPort *con;
struct StandardPacket *packet=NULL;
struct InfoData *id=NULL;
/* open the console device */
if ((OpenDevice("console.device", -1, &ior, 0)) != 0) {
Cleanup(RETURN_FAIL,ERROR_DEVICE_NOT_MOUNTED,NULL,NULL);
}
/* set up the message port in the I/O request */
if ((iorp.mp_SigBit = AllocSignal(-1)) < 0) {
Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,NULL,NULL);
}
iorp.mp_SigTask = (struct Task*)Pr;
/* try to find console associated with calling process */
/* if started from CLI, than is */
if ((iorp.mp_SigTask->tc_Node.ln_Type == NT_PROCESS)) {
con = (struct MsgPort *)
((struct Process *) iorp.mp_SigTask) -> pr_ConsoleTask;
if (con != 0) {
if ((packet = (struct StandardPacket *)
ArpAlloc(sizeof(*packet)))) {
if ((id = (struct id *) ArpAlloc(sizeof(*id)))) {
/* this is the console handlers packet port */
packet->sp_Msg.mn_Node.ln_Name = &(packet->sp_Pkt);
packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
packet->sp_Pkt.dp_Port = &iorp;
packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
packet->sp_Pkt.dp_Arg1 = ((ULONG) id) >> 2;
PutMsg(con, packet);
WaitPort(&iorp);
/* Pointer to console window, all we need..*/
return( (struct Window*)(id->id_VolumeNode));
}
}
}
/* error */
return((struct Window *)-1);
}
}
/* function to display filenames */
VOID Disp(de,max)
struct DirectoryEntry *de;
LONG max;
{
TEXT Name[108];
REGISTER TEXT *from;
REGISTER WORD i,j,
/* number of filenames to be displayed in a row, according
to the CLI window and its (fixedwidth!) font's sizes */
nitems = (((CliWin->Width-24)/CliWin->RPort->Font->tf_XSize)/(max+1));
REGISTER BPTR fh = Output();
REGISTER BOOL Flag;
/* if the window is just too small */
if (nitems < 1) nitems = 1;
while (de) {
/* check for ^C */
if (SetSignal(0,0) & SIGBREAKF_CTRL_C) {
Puts("***Break");
Cleanup(RETURN_WARN,NULL,FileList,NULL);
}
/* display a row of filenames */
for(i=1; (i <= nitems) && de ; i++){
from = de->de_Name;
/* pad Name string with blanks to columnize names */
Flag = TRUE;
for (j = 0; j < max ;j++) {
if (*(from + j) && Flag) *(Name + j) = *(from + j);
else {
Flag = FALSE;
*(Name + j) = ' ';
}
}
Name[max] = '\0';
/* display filenames, Write()s are faster than a single Printf() */
if (de->de_Flags && !argv[NOCOL]) {
Write(fh,"\033[33m",5);
Write(fh,Name,max);
Write(fh," \033[31m",6);
}
else { Write(fh,Name,max);
Write(fh," ",1);
}
de = de->de_Next;
}
/* carriage return */
Write(fh,"\n",1);
}
}
/* get filenames with Anchors, put them in a ordered DAList, display
directory name, date, size and # of files */
VOID ShowDir()
{
TEXT EnvBuf[2]; /* buffer to hold the value of 'dateformat'
environment variable */
REGISTER struct DirectoryEntry *De;
REGISTER struct AnchorPath *Anchor=NULL;
REGISTER LONG Result,m,max=0;
REGISTER ULONG Dirs=0,Files=0,Size=0,NumBlocks=0;
struct DateTime *Dat;
/* Initialize Stamptostr() stuff */
Dat = &D;
Dat->dat_StrDay = Day;
Dat->dat_StrDate = Date;
Dat->dat_StrTime = Time;
/* Allocate space for anchorpath */
if ( Anchor = (struct AnchorPath *)ArpAlloc( (ULONG)sizeof( *Anchor )) )
{
Anchor->ap_Length = 0; /* No path required */
Anchor->ap_BreakBits = SIGBREAKF_CTRL_C; /* stop if ^C */
}
else
{
Puts("Error:No memory");
Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,NULL,NULL);
}
/* examine files specified by pattern */
Result = FindFirst(argv[PAT],Anchor);
while ( Result == 0 )
{
/* the __builtin_ is the way Lattice inserts inline string functions;
with other compilers use a corresponding construct (if any) */
if((m = __builtin_strlen(Anchor->ap_Info.fib_FileName)) > max)
max = m;
/* add filename to ordered DAList */
if ( !(De=AddDANode(Anchor->ap_Info.fib_FileName,
&FileList, 0L, 0L)))
{
Puts("Error: no memory");
Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,FileList,Anchor);
}
/* update files-size counts & mark entry as dir or file */
if (Anchor->ap_Info.fib_DirEntryType >= 0) {
Dirs++;
De->de_Flags = (BYTE) 1;
}
else {
De->de_Flags = (BYTE) 0;
Files++;
}
Size += Anchor->ap_Info.fib_Size;
NumBlocks +=Anchor->ap_Info.fib_NumBlocks+1;
Result = FindNext((struct AnchorPath*) Anchor );
}
/* Free the Anchor chain */
FreeAnchorChain( Anchor );
/* error handling */
if (Result == ERROR_OBJECT_NOT_FOUND) {
Printf("Error:Can't find %s\n",argv[PAT]);
Cleanup(RETURN_ERROR,Result,FileList,NULL);
}
else if (Result == ERROR_BREAK) {
Puts("***Break");
Cleanup(RETURN_WARN,NULL,FileList,NULL);
}
else if (Result != ERROR_NO_MORE_ENTRIES) {
Puts("Error");
Cleanup(RETURN_ERROR,Result,FileList,NULL);
}
argv[PAT][strlen(argv[PAT])-strlen(BaseName(argv[PAT]))] = '\0';
/* empty pattern = current directory */
if (*argv[PAT]) Lck = ArpLock(argv[PAT],ACCESS_READ);
else Lck = Pr->pr_CurrentDir;
PathName(Lck,Buf,255);
/* check for dateformat environment variable and consequentially
act over DateTime structure */
if(Getenv("dateformat",EnvBuf,2))
switch (EnvBuf[0]) {
case '1':
Dat->dat_Format = FORMAT_INT;
break;
case '2':
Dat->dat_Format = FORMAT_USA;
break;
case '3':
Dat->dat_Format = FORMAT_CDN;
break;
};
/* display directory path with current date/time */
DateStamp((long *)Dat);
StamptoStr(Dat);
Printf("\"%s\" on %s %s %s\n",Buf,Day,Date,Time);
Disp(FileList,max);
/* display disk occupation and number of files */
if (Dirs && !(Files))
Printf("%ld blocks in %ld dirs.\n",NumBlocks,Dirs);
else if (Files || Dirs) {
Printf("%ld bytes, %ld blocks in %ld files",Size,NumBlocks,Files);
if (Dirs) Printf(" and %ld dirs.\n",Dirs);
else Printf(".\n");
}
else Puts("Directory or Volume is empty");
FreeDAList(FileList);
}
/* _main used instead of main to slim code */
VOID _main(Line)
STRPTR Line;
{
Pr = (struct Process *) FindTask(NULL);
if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion)))
exit(20);
IntuitionBase = (struct IntuitionBase *)ArpBase->IntuiBase;
if((CliWin = GetWin()) == (struct Window *)-1)
Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,NULL,NULL);
/* parse command line */
for (argc=0; argc < NARGS; ++argc)
argv[argc] = (STRPTR) NULL;
while(*Line > ' ')
++Line;
argc = GADS(++Line,
strlen(Line),
"\nUsage: L Pattern [CD] [NOCOL]\n",
argv,
"PAT,CD/S,NOCOL/S");
/* analyze user given pattern and make it suitable for FindFirst()
and FindNext() */
/* parent dir */
if (!Strcmp(argv[PAT],"/")) {
strcat(Bf,"/*");/* Why in the world do I have to */
argv[PAT]=Bf; /* do this mess to keep code */
} /* LIB:cres.o compatible ?????? */
/* root dir */
else if (!Strcmp(argv[PAT],":")) {
strcat(Bf,":*");
argv[PAT]=Bf;
}
/* current dir */
else if (*argv[PAT] == '\0') {
strcat(Bf,"*");
argv[PAT]=Bf;
}
/* some dir */
else {
if (Lck=Lock(argv[PAT],ACCESS_READ)) /* something on disk ? */
{
if(!(Fib=ArpAllocMem(sizeof(struct FileInfoBlock),
MEMF_CLEAR)))
Cleanup(RETURN_FAIL,
ERROR_NO_FREE_STORE,NULL,NULL);
(VOID)Examine(Lck,Fib);
/* really a directory ? */
if (Fib->fib_DirEntryType >= 0) {
strcpy(Bf,argv[PAT]);
if (argv[PAT][strlen(argv[PAT])-1] == ':')
strcat(Bf,"*");
else strcat(Bf,"/*");
argv[PAT]=Bf;
}
UnLock(Lck);
}
}
ShowDir();
/* if required change the current dir with listed directory in a
PROMPT "%S" compatible way */
if (argv[CD]) {
/* get directory name */
argv[PAT][strlen(argv[PAT])-strlen(BaseName(argv[PAT]))] = '\0';
if (argv[PAT][strlen(argv[PAT])-1] == '/')
argv[PAT][strlen(argv[PAT])-1] = '\0';
/* null pattern = current dir */
if (*argv[PAT]) {
/* change the current dir lock */
Lck = Lock(argv[PAT],ACCESS_READ);
UnLock(Pr->pr_CurrentDir);
Pr->pr_CurrentDir = Lck;
}
else Lck = Pr->pr_CurrentDir; /* or keep it ..*/
PathName(Lck,Buf,255);
CtoBStr(Buf,(BSTR)((((struct CommandLineInterface *)
((Pr->pr_CLI) << 2))->cli_SetName)),255);
}
Cleanup(RETURN_OK,NULL,NULL,NULL);
}