home *** CD-ROM | disk | FTP | other *** search
- /*
- 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);
- }
-
-