home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff284.lzh / ARPTools / src / L.c < prev    next >
C/C++ Source or Header  |  1989-11-27  |  11KB  |  448 lines

  1. /*
  2.           L - Display files and directories in columns.
  3.  
  4.           Original effort by Fabio Rossetti.
  5.  
  6.           (c) 1989 by Fabio Rossetti
  7.  
  8.           To compile under Lattice C v5.0x use:
  9.  
  10.         lc -O -v -cus l
  11.         blink lib:cres.o l.o to l lib lib:a.lib lib:lc.lib sd nd
  12.  
  13. */
  14.  
  15. #include <exec/types.h>
  16. #include <exec/ports.h>
  17. #include <exec/io.h>
  18. #include <exec/memory.h>
  19. #include <exec/libraries.h>
  20.  
  21. #include <devices/console.h>
  22. #include <devices/conunit.h>
  23.  
  24. #include <libraries/dos.h>
  25. #include <libraries/dosextens.h>
  26. #include <libraries/arpbase.h>
  27.  
  28. #include <intuition/intuitionbase.h>
  29. #include <intuition/intuition.h>
  30.  
  31. #include <graphics/text.h>
  32.  
  33. #include <arpfunctions.h>
  34. #include <proto/exec.h>
  35. #include <proto/intuition.h>
  36. #include <proto/dos.h>
  37.  
  38. /* command line arguments */
  39. #define PAT 0
  40. #define CD 1
  41. #define NOCOL 2
  42. #define NARGS 3 /* their # */
  43.  
  44. /*        */
  45. /* global */
  46. /*        */
  47.  
  48. struct ArpBase *ArpBase;
  49. struct IntuitionBase *IntuitionBase;
  50. struct Window *CliWin;     /* pointer to console window */
  51. struct Process *Pr;
  52.  
  53. /* line arguments stuff, must be accessed by several functions */
  54. LONG argc;
  55. STRPTR argv[NARGS];
  56.  
  57. /* general purpose string buffers */
  58. TEXT Bf[256]="\0";
  59. TEXT Buf[256]="\0";
  60.  
  61. /* general purpose lock pointer */
  62. BPTR Lck;
  63.  
  64. struct FileInfoBlock *Fib;            
  65. TEXT *Path;
  66.  
  67. /* this is exec stuff for GetWin, to be kept global for Cleanup() */
  68. struct MsgPort iorp = {
  69.     {0, 0, NT_MSGPORT, 0, 0}, 0,
  70.     -1,                /* initialize signal to -1 */
  71.     0,
  72.                 /* start with empty list */
  73.     {&iorp.mp_MsgList.lh_Tail, 0, &iorp.mp_MsgList.lh_Head, 0, 0}
  74. };
  75. struct IOStdReq ior = {
  76.     {{0, 0, 0, 0, 0}, &iorp, 0},
  77.     0                /* device is zero */
  78. };
  79. /* pointer to ordered list of files to be displayed */
  80. struct DirectoryEntry *FileList = NULL;
  81.  
  82. /* Stamptostr() stuff, kept global for future expansions and v5.0 quirks */
  83. struct DateTime D =
  84.     {
  85.     0L,0L,0L,
  86.     FORMAT_DOS,
  87.     NULL,
  88.     NULL,
  89.     NULL,
  90.     NULL };
  91.  
  92. TEXT     Date[LEN_DATSTRING],
  93.     Time[LEN_DATSTRING],
  94.     Day[LEN_DATSTRING];    
  95.  
  96.  
  97.  
  98. VOID MemCleanup()
  99. {
  100. }
  101.  
  102. /* general shutdown routine*/
  103. VOID Cleanup(code,retcode,filelist,anchor)
  104. LONG code;
  105. LONG retcode;
  106. struct DirectoryEntry *filelist;
  107. struct AnchorPath *anchor;
  108.  
  109. {
  110.     if (ior.io_Device != 0) {
  111.         if (iorp.mp_SigBit != -1) {
  112.         FreeSignal(iorp.mp_SigBit);
  113.         }
  114.         CloseDevice(&ior);
  115.     }
  116.  
  117.     CloseLibrary((struct Library*)ArpBase);
  118.  
  119.     if (anchor) FreeAnchorChain(anchor);
  120.     if (filelist) FreeDAList(filelist);
  121.  
  122.     Pr->pr_Result2=retcode; 
  123.  
  124.     exit(code);
  125. }
  126. /* bulletproofly obtain a pointer to the CLI window sending a ACTION_DISK_INFO
  127.    packet to the console process and looking into InfoData */
  128. struct Window *GetWin()
  129.  
  130. {
  131.     struct MsgPort *con;
  132.     struct StandardPacket *packet=NULL;
  133.     struct InfoData *id=NULL;
  134.  
  135.     /* open the console device */
  136.     if ((OpenDevice("console.device", -1, &ior, 0)) != 0) {
  137.     Cleanup(RETURN_FAIL,ERROR_DEVICE_NOT_MOUNTED,NULL,NULL);
  138.     }
  139.  
  140.     /* set up the message port in the I/O request */
  141.     if ((iorp.mp_SigBit = AllocSignal(-1)) < 0) {
  142.     Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,NULL,NULL);
  143.     }
  144.     iorp.mp_SigTask = (struct Task*)Pr;
  145.  
  146.     /* try to find console associated with calling process */
  147.     /* if started from CLI, than is  */
  148.     if ((iorp.mp_SigTask->tc_Node.ln_Type == NT_PROCESS)) {
  149.     con = (struct MsgPort *) 
  150.         ((struct Process *) iorp.mp_SigTask) -> pr_ConsoleTask;
  151.     if (con != 0) {
  152.         if ((packet = (struct StandardPacket *)
  153.             ArpAlloc(sizeof(*packet)))) {
  154.         if ((id = (struct id *) ArpAlloc(sizeof(*id)))) {
  155.             /* this is the console handlers packet port */
  156.             packet->sp_Msg.mn_Node.ln_Name = &(packet->sp_Pkt);
  157.             packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  158.             packet->sp_Pkt.dp_Port = &iorp;
  159.             packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
  160.             packet->sp_Pkt.dp_Arg1 = ((ULONG) id) >> 2;
  161.             PutMsg(con, packet);
  162.              WaitPort(&iorp);
  163.             /* Pointer to console window, all we need..*/
  164.             return( (struct Window*)(id->id_VolumeNode));
  165.         }
  166.     }
  167.     }
  168.     /* error */
  169.     return((struct Window *)-1);
  170. }
  171. }
  172. /* function to display filenames */
  173. VOID Disp(de,max)
  174. struct DirectoryEntry *de;
  175. LONG max;
  176.  
  177. {
  178.     TEXT Name[108];
  179.     REGISTER TEXT *from;
  180.     REGISTER WORD i,j,
  181.     /* number of filenames to be displayed in a row, according
  182.        to the CLI window and its (fixedwidth!) font's sizes */
  183.     nitems =  (((CliWin->Width-24)/CliWin->RPort->Font->tf_XSize)/(max+1));
  184.     
  185.     REGISTER BPTR fh = Output();
  186.     REGISTER BOOL Flag;
  187.  
  188.     /* if the window is just too small */
  189.     if (nitems < 1) nitems = 1;
  190.  
  191.     while (de) {
  192.  
  193.     /* check for ^C */
  194.     if (SetSignal(0,0) & SIGBREAKF_CTRL_C) {
  195.         Puts("***Break");
  196.         Cleanup(RETURN_WARN,NULL,FileList,NULL);
  197.         }
  198.  
  199.     /* display a row of filenames */
  200.     for(i=1; (i <= nitems) && de ; i++){
  201.  
  202.     from = de->de_Name;
  203.  
  204.     /* pad Name string with blanks to columnize names */
  205.     Flag = TRUE;
  206.         for (j = 0; j < max ;j++) {
  207.             if (*(from + j) && Flag) *(Name + j) = *(from + j);
  208.             else {
  209.                 Flag = FALSE;
  210.                 *(Name + j) = ' ';
  211.                  }
  212.         }
  213.     Name[max] = '\0';
  214.     
  215.     /* display filenames, Write()s are faster than a single Printf() */
  216.     if (de->de_Flags && !argv[NOCOL]) {
  217.          Write(fh,"\033[33m",5);
  218.          Write(fh,Name,max);
  219.          Write(fh," \033[31m",6);            
  220.         }
  221.     else {    Write(fh,Name,max);
  222.         Write(fh," ",1);            
  223.         }
  224.     de = de->de_Next;
  225.     }
  226.     /* carriage return */
  227.     Write(fh,"\n",1);
  228.         }    
  229. }
  230.  
  231. /* get filenames with Anchors, put them in a ordered DAList, display
  232.    directory name, date, size and # of files */ 
  233. VOID ShowDir()
  234.  
  235. {
  236.     TEXT EnvBuf[2]; /* buffer to hold the value of 'dateformat'
  237.                environment variable */
  238.     REGISTER struct DirectoryEntry *De;
  239.     REGISTER struct AnchorPath *Anchor=NULL;
  240.     REGISTER LONG Result,m,max=0;
  241.     REGISTER ULONG Dirs=0,Files=0,Size=0,NumBlocks=0;
  242.     struct DateTime *Dat;
  243.  
  244.     /* Initialize Stamptostr() stuff */
  245.     Dat = &D;
  246.     Dat->dat_StrDay = Day;
  247.     Dat->dat_StrDate = Date;
  248.     Dat->dat_StrTime = Time;
  249.  
  250.     /* Allocate space for anchorpath */     
  251.     if ( Anchor = (struct AnchorPath *)ArpAlloc( (ULONG)sizeof( *Anchor )) )
  252.     {
  253.         Anchor->ap_Length = 0; /* No path required */
  254.         Anchor->ap_BreakBits = SIGBREAKF_CTRL_C; /* stop if ^C */
  255.     }
  256.     else
  257.     {
  258.         Puts("Error:No memory");
  259.         Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,NULL,NULL);
  260.     }
  261.  
  262.     /* examine files specified by pattern */ 
  263.     Result = FindFirst(argv[PAT],Anchor);
  264.  
  265.     while ( Result == 0 )
  266.     {
  267.         /* the __builtin_ is the way Lattice inserts inline string functions;
  268.            with other compilers use a corresponding construct (if any) */
  269.         if((m = __builtin_strlen(Anchor->ap_Info.fib_FileName)) > max)
  270.                              max = m;
  271.         /* add filename to ordered DAList */ 
  272.         if ( !(De=AddDANode(Anchor->ap_Info.fib_FileName,
  273.                      &FileList, 0L, 0L)))
  274.         {
  275.             Puts("Error: no memory");
  276.             Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,FileList,Anchor);
  277.         }
  278.         /* update files-size counts & mark entry as dir or file */
  279.         if (Anchor->ap_Info.fib_DirEntryType >= 0) {
  280.                 Dirs++;
  281.                 De->de_Flags = (BYTE) 1;
  282.                 }
  283.         else {
  284.             De->de_Flags = (BYTE) 0;
  285.             Files++;
  286.             }
  287.         Size += Anchor->ap_Info.fib_Size;
  288.         NumBlocks +=Anchor->ap_Info.fib_NumBlocks+1;
  289.  
  290.         Result = FindNext((struct AnchorPath*) Anchor );
  291.     }
  292.  
  293.     /* Free the Anchor chain */
  294.       FreeAnchorChain( Anchor );
  295.  
  296.     /* error handling */
  297.     if (Result == ERROR_OBJECT_NOT_FOUND) {
  298.         Printf("Error:Can't find %s\n",argv[PAT]);
  299.         Cleanup(RETURN_ERROR,Result,FileList,NULL);
  300.     }
  301.     else if (Result == ERROR_BREAK) {
  302.         Puts("***Break");
  303.         Cleanup(RETURN_WARN,NULL,FileList,NULL);
  304.             }
  305.     else if (Result != ERROR_NO_MORE_ENTRIES) {
  306.         Puts("Error");
  307.         Cleanup(RETURN_ERROR,Result,FileList,NULL);
  308.     }
  309.  
  310.     argv[PAT][strlen(argv[PAT])-strlen(BaseName(argv[PAT]))] = '\0';    
  311.     /* empty pattern = current directory */
  312.     if (*argv[PAT]) Lck = ArpLock(argv[PAT],ACCESS_READ);
  313.     else Lck = Pr->pr_CurrentDir;
  314.     PathName(Lck,Buf,255);
  315.  
  316.     /* check for dateformat environment variable and consequentially
  317.        act over DateTime structure */
  318.     if(Getenv("dateformat",EnvBuf,2))
  319.     switch (EnvBuf[0]) {
  320.         case '1':
  321.         Dat->dat_Format = FORMAT_INT;
  322.         break;
  323.         case '2':
  324.         Dat->dat_Format = FORMAT_USA;
  325.         break;
  326.         case '3':
  327.         Dat->dat_Format = FORMAT_CDN;
  328.         break;
  329.      };
  330.  
  331.     /* display directory path with current date/time */
  332.     DateStamp((long *)Dat);
  333.     StamptoStr(Dat);
  334.     Printf("\"%s\" on %s %s %s\n",Buf,Day,Date,Time);
  335.  
  336.     Disp(FileList,max);
  337.  
  338.     /* display disk occupation and number of files */
  339.     if (Dirs && !(Files))
  340.         Printf("%ld blocks in %ld dirs.\n",NumBlocks,Dirs);
  341.         else if (Files || Dirs) {
  342.     Printf("%ld bytes, %ld blocks in %ld files",Size,NumBlocks,Files);
  343.     if (Dirs) Printf(" and %ld dirs.\n",Dirs);
  344.     else Printf(".\n");
  345.     }
  346.     else Puts("Directory or Volume is empty");        
  347.  
  348.     FreeDAList(FileList);
  349.     
  350.         
  351. }
  352.  
  353.  
  354. /* _main used instead of main to slim code */
  355. VOID _main(Line)
  356. STRPTR Line;
  357.  
  358. {
  359.         
  360.     Pr = (struct Process *) FindTask(NULL);
  361.     if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion)))
  362.          exit(20);
  363.     
  364.     IntuitionBase = (struct IntuitionBase *)ArpBase->IntuiBase;
  365.  
  366.     if((CliWin = GetWin()) == (struct Window *)-1)
  367.         Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,NULL,NULL);
  368.  
  369.     /* parse command line */
  370.     for (argc=0; argc < NARGS; ++argc)
  371.         argv[argc] = (STRPTR) NULL;
  372.  
  373.     while(*Line > ' ')
  374.         ++Line;
  375.  
  376.     argc = GADS(++Line,
  377.             strlen(Line),
  378.             "\nUsage: L Pattern [CD] [NOCOL]\n",
  379.             argv,
  380.             "PAT,CD/S,NOCOL/S");
  381.  
  382.  
  383.     /* analyze user given pattern and make it suitable for FindFirst()
  384.        and FindNext() */
  385.  
  386.     /* parent dir */
  387.      if (!Strcmp(argv[PAT],"/")) {
  388.                 strcat(Bf,"/*");/* Why in the world do I have to */
  389.                 argv[PAT]=Bf;    /* do this mess to keep code     */
  390.                     }    /* LIB:cres.o compatible ??????  */
  391.     /* root dir */
  392.     else if (!Strcmp(argv[PAT],":")) {
  393.                 strcat(Bf,":*");
  394.                 argv[PAT]=Bf;
  395.                     }
  396.     /* current dir */
  397.     else if (*argv[PAT] == '\0')  {
  398.                 strcat(Bf,"*");
  399.                 argv[PAT]=Bf;
  400.                 }
  401.     /* some dir */
  402.     else {
  403.         if (Lck=Lock(argv[PAT],ACCESS_READ)) /* something on disk ? */ 
  404.             {
  405.             if(!(Fib=ArpAllocMem(sizeof(struct FileInfoBlock),
  406.                     MEMF_CLEAR))) 
  407.                     Cleanup(RETURN_FAIL,
  408.                     ERROR_NO_FREE_STORE,NULL,NULL);
  409.             
  410.             (VOID)Examine(Lck,Fib);
  411.             /* really a directory ? */
  412.             if (Fib->fib_DirEntryType >= 0) {
  413.                 strcpy(Bf,argv[PAT]);
  414.                 if (argv[PAT][strlen(argv[PAT])-1] == ':') 
  415.                 strcat(Bf,"*");
  416.                 else strcat(Bf,"/*");
  417.                 argv[PAT]=Bf;
  418.  
  419.                 }
  420.             UnLock(Lck);
  421.             }
  422.         }    
  423.                 
  424.     ShowDir();
  425.  
  426.     /* if required change the current dir with listed directory in a 
  427.        PROMPT "%S" compatible way */
  428.     if (argv[CD]) {
  429.         /* get directory name */
  430.         argv[PAT][strlen(argv[PAT])-strlen(BaseName(argv[PAT]))] = '\0';
  431.         if (argv[PAT][strlen(argv[PAT])-1] == '/') 
  432.                 argv[PAT][strlen(argv[PAT])-1] = '\0';
  433.         /* null pattern = current dir */
  434.         if (*argv[PAT]) {
  435.             /* change the current dir lock */
  436.             Lck = Lock(argv[PAT],ACCESS_READ);
  437.             UnLock(Pr->pr_CurrentDir);
  438.             Pr->pr_CurrentDir = Lck;
  439.             }
  440.         else Lck = Pr->pr_CurrentDir; /* or keep it ..*/
  441.         PathName(Lck,Buf,255);
  442.         CtoBStr(Buf,(BSTR)((((struct CommandLineInterface *)
  443.             ((Pr->pr_CLI) << 2))->cli_SetName)),255);    
  444.         }
  445.     Cleanup(RETURN_OK,NULL,NULL,NULL);
  446. }
  447.  
  448.