home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Tools / nShell™ 1.0.3 / MoreSource / ls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-21  |  11.6 KB  |  533 lines  |  [TEXT/KAHL]

  1. /* ========================================
  2.  
  3.     ls.c
  4.     
  5.     Copyright (c) 1993,1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ======================================== */
  14.  
  15. #ifdef __MWERKS__            // CodeWarrior requires an A4 setup
  16. #include <A4Stuff.h>
  17. #endif
  18.  
  19. #include <Packages.h>
  20.  
  21. #define LS_BUF_SIZ    4000
  22.    
  23. #include "nshc.h"
  24.                     
  25. #include "arg_utl.proto.h"
  26. #include "str_utl.proto.h"
  27. #include "nshc_utl.proto.h"
  28.  
  29. /* ======================================== */
  30.  
  31. void format_size( long size, char *p );
  32.  
  33. void format_size( long size, char *p )
  34. {
  35.     char    units;
  36.     
  37.     units = ' ';
  38.     
  39.     if (size > 9999) {
  40.         size /= 1024;
  41.         units = 'k';
  42.         }
  43.     
  44.     if (size > 9999) {
  45.         size /= 1024;
  46.         units = 'M';
  47.         }
  48.     
  49.     cStrFromNum( p, 4, size );
  50.     
  51.     p += 4;
  52.         
  53.     *p++ = units;
  54. }
  55.  
  56. /* ======================================== */
  57.  
  58. short ls_volume( Str255 path );
  59.  
  60. short ls_volume( Str255 path )
  61. {
  62.     Str255            localPath;
  63.     HParamBlockRec    pb;
  64.  
  65.     pb.volumeParam.ioCompletion = 0;
  66.     pb.volumeParam.ioNamePtr = localPath;
  67.     pb.volumeParam.ioVRefNum = 0;
  68.     pb.volumeParam.ioVolIndex = -1;
  69.     pStrCopy( localPath, path );
  70.         
  71.     if (!PBHGetVInfo(&pb, FALSE))
  72.         return( pb.volumeParam.ioVRefNum );
  73.     else
  74.         return(0);
  75. }
  76.  
  77. /* ======================================== */
  78.  
  79. void long_header( t_nshc_calls *nshc_calls, int option_time );
  80.  
  81. void long_header( t_nshc_calls *nshc_calls, int option_time )
  82. {
  83.     switch( option_time ) {
  84.         case 'g' :
  85.             nshc_calls->NSH_putStr("\p\r Crea Type RSize DSize  Creation Date       Name");
  86.             break;
  87.         case 'b' :
  88.             nshc_calls->NSH_putStr("\p\r Crea Type RSize DSize  Backup Date         Name");
  89.             break;
  90.         default :
  91.             nshc_calls->NSH_putStr("\p\r Crea Type RSize DSize  Modification Date   Name");
  92.             break;
  93.         }
  94.     nshc_calls->NSH_putStr("\p\r ---- ---- ----- ----- -------------------- ----\r");
  95. }
  96.  
  97. /* ======================================== */
  98.  
  99. int show_long( t_nshc_calls *nshc_calls, HFileInfo *fpb, Str255 path, int option_time );
  100.  
  101. int show_long( t_nshc_calls *nshc_calls, HFileInfo *fpb, Str255 path, int option_time )
  102. {
  103.     int            i;
  104.     int            index;
  105.     OSType        type;
  106.     char        *p;
  107.     char        line[LS_BUF_SIZ];
  108.     long        value;
  109.     Str255        string;
  110.     
  111.     index = 0;
  112.     line[index++] = ' ';
  113.  
  114.     if (fpb->ioFlAttrib & 16) {
  115.  
  116.         for (i=1; i<23; i++) line[index++] = ' ';
  117.                 
  118.         switch( option_time ) {
  119.             case 'g' :
  120.                 value = ((DirInfo *)fpb)->ioDrCrDat;
  121.                 break;
  122.             case 'b' :
  123.                 value = ((DirInfo *)fpb)->ioDrBkDat;
  124.                 break;
  125.             default :
  126.                 value = ((DirInfo *)fpb)->ioDrMdDat;
  127.                 break;
  128.             }                
  129.     
  130.         IUDateString( value, shortDate, string );
  131.         for (i=1; i<=(8 - string[0]); i++) line[index++] = ' ';
  132.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  133.         line[index++] = ' ';
  134.         
  135.         IUTimeString( value, 1, string );
  136.         for (i=1; i<=(11 - string[0]); i++) line[index++] = ' ';
  137.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  138.         line[index++] = ' ';
  139.         
  140.         }
  141.     else {
  142.             
  143.         type = fpb->ioFlFndrInfo.fdCreator;        
  144.         p = (char *) &type;
  145.         for ( i=0; i<4; i++ ) line[index++] = *p++;
  146.         line[index++] = ' ';
  147.     
  148.         type = fpb->ioFlFndrInfo.fdType;        
  149.         p = (char *) &type;
  150.         for ( i=0; i<4; i++ ) line[index++] = *p++;
  151.         line[index++] = ' ';
  152.         
  153.         format_size( (fpb->ioFlRLgLen), &line[index] );
  154.         index += 5;
  155.         line[index++] = ' ';
  156.         
  157.         format_size( (fpb->ioFlLgLen), &line[index] );
  158.         index += 5;
  159.         line[index++] = ' ';
  160.         
  161.         switch( option_time ) {
  162.             case 'g' :
  163.                 value = fpb->ioFlCrDat;
  164.                 break;
  165.             case 'b' :
  166.                 value = fpb->ioFlBkDat;
  167.                 break;
  168.             default :
  169.                 value = fpb->ioFlMdDat;
  170.                 break;
  171.             }
  172.                 
  173.         IUDateString( value, shortDate, string );
  174.         for (i=1; i<=(8 - string[0]); i++) line[index++] = ' ';
  175.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  176.         line[index++] = ' ';
  177.         
  178.         IUTimeString( value, 1, string );
  179.         for (i=1; i<=(11 - string[0]); i++) line[index++] = ' ';
  180.         for (i=1; i<=string[0]; i++) line[index++] = string[i];
  181.         line[index++] = ' ';
  182.         }
  183.         
  184.     for ( i=1; i<=path[0]; i++ )
  185.         line[index++] = path[i];
  186.             
  187.     line[index++] = '\r';
  188.     line[index] = 0;
  189.         
  190.     nshc_calls->NSH_puts(line);
  191. }
  192.  
  193. /* ======================================== */
  194.  
  195. int do_long( t_nshc_calls *nshc_calls, short volume, Str255 path, int option_time, int is_list, int first_call );
  196.  
  197. int do_long( t_nshc_calls *nshc_calls, short volume, Str255 path, int option_time, int is_list, int first_call )
  198. {
  199.     CInfoPBRec    cipbr;
  200.     HFileInfo    *fpb;
  201.     short        idx;
  202.     long        foundDir;
  203.     Str255        localPath;
  204.     
  205.     fpb = (HFileInfo *)&cipbr;
  206.     
  207.     fpb->ioVRefNum = volume;
  208.     fpb->ioDirID = 0;
  209.     fpb->ioFDirIndex = 0;
  210.     fpb->ioNamePtr = localPath;
  211.     pStrCopy( localPath, path );
  212.  
  213.     if (PBGetCatInfo( &cipbr, FALSE )) {
  214.         nshc_calls->NSH_putStr_err("\pls: ioDirID not found.\r");
  215.         return(1);
  216.         }
  217.         
  218.     foundDir = fpb->ioDirID;
  219.  
  220.     if (fpb->ioFlAttrib & 16) {
  221.         if (is_list) {
  222.             nshc_calls->NSH_putStr("\p\rDir = ");
  223.             nshc_calls->NSH_putStr(path);
  224.             nshc_calls->NSH_putStr("\p\r\r");
  225.             }
  226.         if (is_list || first_call) {
  227.             long_header( nshc_calls, option_time );
  228.             }
  229.         for( idx=1; TRUE; idx++) {                        /* indexing loop */
  230.             fpb->ioVRefNum = volume;
  231.             fpb->ioDirID = foundDir;                    /* must set on each loop */
  232.             fpb->ioFDirIndex = idx;
  233.             pStrCopy( localPath, path );
  234.         
  235.             if (PBGetCatInfo( &cipbr, FALSE )) break;    /* exit when no more entries */
  236.  
  237.             show_long( nshc_calls, fpb, localPath, option_time );
  238.             }
  239.         nshc_calls->NSH_putchar('\r');
  240.         }
  241.     else
  242.         show_long( nshc_calls, fpb, localPath, option_time );
  243.  
  244.     return(0);
  245. }
  246.  
  247.  /* ======================================== */
  248.  
  249. int do_cols( t_nshc_calls *nshc_calls, short volume, Str255 path, int cols, int is_list );
  250.  
  251. int do_cols( t_nshc_calls *nshc_calls, short volume, Str255 path, int cols, int is_list )
  252. {
  253.     CInfoPBRec    cipbr;
  254.     HFileInfo    *fpb;
  255.     short        idx;
  256.     long        foundDir;
  257.     Str255        localPath;
  258.     int            blanks;
  259.     int            count;
  260.     int            column_width;
  261.     int            i, cmax;
  262.     int            buf_ptr;
  263.     char        buf[LS_BUF_SIZ];
  264.  
  265.     fpb = (HFileInfo *)&cipbr;
  266.     
  267.     fpb->ioVRefNum = volume;
  268.     fpb->ioDirID = 0;
  269.     fpb->ioFDirIndex = 0;
  270.     fpb->ioNamePtr = localPath;
  271.     pStrCopy( localPath, path );
  272.  
  273.     if (PBGetCatInfo( &cipbr, FALSE )) {
  274.         nshc_calls->NSH_putStr_err("\pls: ioDirID not found.\r");
  275.         return(1);
  276.         }
  277.         
  278.     if (fpb->ioFlAttrib & 16) {
  279.     
  280.         if (is_list) {
  281.             nshc_calls->NSH_putStr("\p\rDir = ");
  282.             nshc_calls->NSH_putStr(path);
  283.             nshc_calls->NSH_putStr("\p\r\r");
  284.             }
  285.  
  286.         foundDir = fpb->ioDirID;
  287.         count = 0;
  288.  
  289.         column_width = 0;
  290.  
  291.         for( idx=1; TRUE; idx++) {
  292.             fpb->ioVRefNum = volume;
  293.             fpb->ioDirID = foundDir;
  294.             fpb->ioFDirIndex = idx;
  295.             pStrCopy( localPath, path );
  296.             if (PBGetCatInfo( &cipbr, FALSE ))        // returns non-zero when no more
  297.                 break;
  298.             i = localPath[0] + 5;
  299.             if (i > column_width) column_width = i;
  300.             }
  301.         
  302.         buf_ptr = 0;
  303.         
  304.         for( idx=1; TRUE; idx++) {
  305.             fpb->ioVRefNum = volume;
  306.             fpb->ioDirID = foundDir;
  307.             fpb->ioFDirIndex = idx;
  308.             pStrCopy( localPath, path );
  309.         
  310.             if (PBGetCatInfo( &cipbr, FALSE ))        // returns non-zero when no more
  311.                 break;
  312.         
  313.             count++;
  314.         
  315.             cmax = localPath[0];
  316.             
  317.             if ( (buf_ptr + column_width + 2 ) > LS_BUF_SIZ ) {
  318.                 buf[buf_ptr] = 0;
  319.                 nshc_calls->NSH_puts(buf);
  320.                 buf_ptr = 0;
  321.                 }
  322.  
  323.             for ( i = 1 ; i <= cmax ; i ++ )
  324.                 buf[buf_ptr++] = localPath[i];
  325.     
  326.             blanks = column_width - cmax;
  327.  
  328.             if (fpb->ioFlAttrib & 16) {
  329.                 buf[buf_ptr++] = ':';
  330.                 blanks--;
  331.                 }
  332.  
  333.             if (count % cols) {
  334.                 while (blanks--)
  335.                     buf[buf_ptr++] = ' ';
  336.                 }
  337.             else {
  338.                 buf[buf_ptr++] = '\r';
  339.                 count = 0;
  340.                 }
  341.             }
  342.     
  343.         if (buf_ptr) {
  344.             buf[buf_ptr++] = '\r';
  345.             buf[buf_ptr] = 0;
  346.             nshc_calls->NSH_puts(buf);
  347.             }
  348.         nshc_calls->NSH_putchar('\r');
  349.         }
  350.     else {
  351.         nshc_calls->NSH_putStr(localPath);
  352.         nshc_calls->NSH_putchar('\r');
  353.         }
  354.  
  355.     
  356.     return(0);
  357. }
  358.  
  359.  /* ======================================== */
  360.  
  361. int do_fast( t_nshc_calls *nshc_calls, short volume, Str255 path, int is_list );
  362.  
  363. int do_fast( t_nshc_calls *nshc_calls, short volume, Str255 path, int is_list )
  364. {
  365.     CInfoPBRec        cipbr;
  366.     HFileInfo        *fpb;
  367.     short            idx;
  368.     long            foundDir;
  369.     Str255            localPath;
  370.     int                ci, cmax;
  371.     int                buf_ptr;
  372.     char            buf[LS_BUF_SIZ];
  373.     
  374.     fpb = (HFileInfo *)&cipbr;
  375.     
  376.     fpb->ioVRefNum = volume;
  377.     fpb->ioDirID = 0;
  378.     fpb->ioFDirIndex = 0;
  379.     fpb->ioNamePtr = localPath;
  380.     pStrCopy( localPath, path );
  381.  
  382.     if (PBGetCatInfo( &cipbr, FALSE )) {
  383.         nshc_calls->NSH_putStr_err("\pls: File or directory not found.\r");
  384.         return(1);
  385.         }
  386.         
  387.     if (fpb->ioFlAttrib & 16) {
  388.  
  389.         if (is_list) {
  390.             nshc_calls->NSH_putStr("\p\rDir = ");
  391.             nshc_calls->NSH_putStr(path);
  392.             nshc_calls->NSH_putStr("\p\r\r");
  393.             }
  394.  
  395.         foundDir = fpb->ioDirID;
  396.         buf_ptr = 0;
  397.  
  398.         for( idx=1; TRUE; idx++) {                        /* indexing loop */
  399.             fpb->ioVRefNum = volume;
  400.             fpb->ioDirID = foundDir;                    /* must set on each loop */
  401.             fpb->ioFDirIndex = idx;
  402.             pStrCopy( localPath, path );
  403.         
  404.             if (PBGetCatInfo( &cipbr, FALSE )) break;    /* exit when no more entries */
  405.             
  406.             cmax = localPath[0];
  407.             
  408.             if ( (buf_ptr + cmax + 3 ) > LS_BUF_SIZ ) {
  409.                 buf[buf_ptr] = 0;
  410.                 nshc_calls->NSH_puts(buf);
  411.                 buf_ptr = 0;
  412.                 }
  413.             else {
  414.                 for ( ci = 1 ; ci <= cmax ; ci ++ )
  415.                     buf[buf_ptr++] = localPath[ci];
  416.  
  417.                 if (fpb->ioFlAttrib & 16)
  418.                     buf[buf_ptr++] = ':';
  419.         
  420.                 buf[buf_ptr++] = '\r';
  421.                 }
  422.             }
  423.             
  424.             if (buf_ptr) {
  425.                 buf[buf_ptr] = 0;
  426.                 nshc_calls->NSH_puts(buf);
  427.                 }
  428.         nshc_calls->NSH_putchar('\r');
  429.         }
  430.     else {
  431.         nshc_calls->NSH_putStr(localPath);
  432.         nshc_calls->NSH_putchar('\r');
  433.         }
  434.     
  435.     return(0);
  436. }
  437.  
  438.   /* ======================================== */ 
  439.  
  440. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  441. {
  442.     int        option_cols;
  443.     int        option_long;
  444.     int        option_time;
  445.     int        cArg;
  446.     int        arg;
  447.     int        argc;
  448.     int        cols;
  449.     Str255    path;
  450.     int        path_ok;
  451.     int        error;
  452.     int        count;
  453.     int        first_call;
  454.     short    volume;
  455.         
  456. #ifdef __MWERKS__
  457.     long oldA4  = SetCurrentA4();
  458. #endif
  459.  
  460.     error = nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION );
  461.     
  462.     if (!error) {
  463.         option_long = nshc_got_option( nshc_parms, 'l' );
  464.         option_cols = nshc_got_option( nshc_parms, 'c' );
  465.         option_time = 'm'; // modification
  466.         if (nshc_got_option( nshc_parms, 'b' )) option_time = 'b';
  467.         if (nshc_got_option( nshc_parms, 'g' )) option_time = 'g';
  468.         if (cArg = nshc_got_option( nshc_parms, 'c' ))
  469.             if ( nshc_is_numeric_operand( nshc_parms, ++cArg ) )
  470.                 cols = arg_to_int( nshc_parms, cArg );
  471.             else {
  472.                 nshc_calls->NSH_putStr_err("\pUsage: ls [<path1> <path2>...] [-c columns] [-l [-m] [-b] [-g]].\r");
  473.                 error = NSHC_ERR_PARMS;
  474.                 }
  475.         }
  476.     
  477.     count = 0;
  478.     
  479.     first_call = 1;
  480.     
  481.     argc = nshc_parms->argc;
  482.     
  483.     for (arg = 1; arg < argc; arg++ )
  484.         if (!error)
  485.             if (arg != cArg)
  486.                 if (nshc_is_operand(nshc_parms, arg)) {
  487.                     count++;
  488.                     pStrFromC( path, &(nshc_parms->arg_buf[nshc_parms->argv[arg]]) );
  489.                     error = nshc_calls->NSH_path_expand(path);
  490.                     if (!error)
  491.                         volume = ls_volume( path );
  492.                     if (!error && volume) {
  493.                         if (option_long)
  494.                             error = do_long(nshc_calls, volume, path, option_time, 1, first_call);
  495.                         else
  496.                             if ((option_cols) && (cols > 1))
  497.                                 error = do_cols(nshc_calls, volume, path, cols, 1);
  498.                             else
  499.                                 error = do_fast(nshc_calls, volume, path, 1);
  500.                         }
  501.                     else
  502.                         nshc_calls->NSH_putStr_err("\pls: File or directory not found.\r");
  503.                     first_call = 0;
  504.                     }
  505.         
  506.     if (!(error || count))
  507.         if (nshc_calls->NSH_var_env( "\pPWD", path )) {
  508.             nshc_calls->NSH_putStr_err("\pls: PWD not found.\r");
  509.             error = 1;
  510.             }
  511.         else
  512.             if ( volume = ls_volume( path ) ) {
  513.                 if (option_long)
  514.                     error = do_long(nshc_calls, volume, path, option_time, 0, 1);
  515.                 else
  516.                     if (option_cols)
  517.                         error = do_cols(nshc_calls, volume, path, cols, 0);
  518.                     else
  519.                         error = do_fast(nshc_calls, volume, path, 0);
  520.                 }
  521.             else {
  522.                 nshc_calls->NSH_putStr_err("\pls: PWD volume not found.\r");
  523.                 error = 1;
  524.                 }
  525.  
  526.     nshc_parms->action = nsh_idle;
  527.     nshc_parms->result = error;
  528.     
  529. #ifdef __MWERKS__
  530.     SetA4(oldA4);
  531. #endif
  532. }
  533.