home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / cdrom / Misc / cdr / CDR.CPP < prev    next >
C/C++ Source or Header  |  1995-05-26  |  30KB  |  1,052 lines

  1. // ----------------------------------------------------------------------------------------------------
  2. //
  3. //                  C O P Y R I G H T    N O T I C E
  4. //
  5. //    The code contained within this source file is copyright
  6. //    N. A. Balharrie, 1995. It may not be reproduced,  used,
  7. //    or altered in any way without the above named copyright
  8. //    holders written permission.
  9. //
  10. // ----------------------------------------------------------------------------------------------------
  11. // TODO Wish List
  12. //
  13. //   - Files extracted with the get command to have the same name as the CDROM.
  14. //   - Wildcards to be added to all file commands.
  15. //   - Directory stack (ie. pushd and popd)
  16. //   - cd should keep trying objects until it finds a match.
  17. //   - Allow for intialisation file.
  18. //   - Allow product information files to be viewed easily.
  19. //   - Allow an index file to be attached, thus allowing a file to be found
  20. //     via a whereis command.
  21. //   - Multiple file extractions
  22. //   - Recursive file extractions.
  23. //   H Filename completion (rudimentary version available via wildcards)
  24. //   - Modify last command.
  25. //   - Command history buffer.
  26. //   - Produce log file at users request.
  27. //
  28. // ----------------------------------------------------------------------------------------------------
  29.  
  30. #include <stdio.h>
  31. #include <conio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <io.h>
  35.  
  36. // ----------------------------------------------------------------------------------------------------
  37.  
  38. #define FALSE   (0)
  39. #define TRUE    (1)
  40.  
  41. // ----------------------------------------------------------------------------------------------------
  42.  
  43. #pragma pack(1)
  44.  
  45. // ----------------------------------------------------------------------------------------------------
  46.  
  47. int file_number = 0;
  48. const int max_lines = 20;
  49. char* output_dir = "";
  50.  
  51. // ----------------------------------------------------------------------------------------------------
  52. // ISO-9660 directory entry structure 
  53.     
  54. typedef struct dir_entry 
  55. {
  56.     unsigned char        len_dr;                // length of this directory entry            
  57.     unsigned char        XAR_len;            // XAR length in LBN's (logical blocks numbers)    
  58.     unsigned long        loc_extentI;        // LBN of data Intel format            
  59.     unsigned long        loc_extentM;        // LBN of data Molorola format            
  60.     unsigned long        data_lenI;            // length of file Intel format            
  61.     unsigned long        data_lenM;            // length of file Motorola format            
  62.     unsigned char        record_time[7];        // date and time                    
  63.     unsigned char        file_flags_iso;        // 8 flags                    
  64.     unsigned char        il_size;            // interleave size                
  65.     unsigned char        il_skip;            // interleave skip factor                
  66.     unsigned short        VSSNI;                // volume set sequence number Intel        
  67.     unsigned short        VSSNM;                // volume set sequence number Motorola    
  68.     unsigned char        len_fi;                // length of name                
  69.     unsigned char        file_id[256];        // variable length name upto 32 chars        
  70. } dir_entry;
  71.  
  72. // ----------------------------------------------------------------------------------------------------
  73. // Primary volume description
  74.  
  75. typedef struct prim_vol_desc {
  76.       unsigned char  type;
  77.       char           id[5];
  78.       unsigned char  version;
  79.       char           pad1;
  80.       char           system_id[32];
  81.       char           volume_id[32];
  82.       char           pad2[8];
  83.       unsigned long  space_size_i;
  84.       unsigned long  space_size_m;
  85.       char           pad3[32];
  86.       unsigned short set_size_i;
  87.       unsigned short set_size_m;
  88.       unsigned short sequence_i;
  89.       unsigned short sequence_m;
  90.       unsigned short block_size_i;
  91.       unsigned short block_size_m;
  92.       unsigned long  path_size_i;
  93.       unsigned long  path_size_m;
  94.       unsigned long  i_table;
  95.       unsigned long  opt_i_table;
  96.       unsigned long  m_table;
  97.       unsigned long  opt_m_table;
  98.       dir_entry      root;
  99.       char           volume_set_id[128];
  100.       char           publisher_id[128];
  101.       char           data_preparer[128];
  102.       char           application_id[128];
  103.       char           copyright[37];
  104.       char           abstract_file_id[37];
  105.       char           bibliographic_id[37];
  106.       char           vol_creation[17];
  107.       char           vol_modification[17];
  108.       char           vol_expiration[17];
  109.       char           vol_effective[17];
  110.       unsigned char  file_structure_version;
  111.       char           pad4;
  112.       char           application_use[512];
  113.       char           reserved[653];
  114. } prim_vol_desc;
  115.  
  116. // ----------------------------------------------------------------------------------------------------
  117.  
  118. const int buffer_length = 2048;
  119.  
  120. class CDROM {
  121. protected:
  122.     void make_string( char _far* string_in, int length );
  123.     
  124. public:
  125.     void read_sector( unsigned long sector, unsigned char _far* buffer );
  126.     void read_voldesc( unsigned char _far* buffer );
  127.     void motorola_to_intel( unsigned long _far* motorola, unsigned long _far* intel );
  128. };
  129.  
  130. // ----------------------------------------------------------------------------------------------------
  131.  
  132. void CDROM::motorola_to_intel( unsigned long _far* motorola, unsigned long _far* intel )
  133. {
  134.     unsigned char old_val[ 4 ];
  135.     unsigned char new_val[ 4 ];
  136.  
  137.     memcpy( (char*)old_val, (char*)motorola, 4 );
  138.     new_val[ 0 ] = old_val[ 3 ];
  139.     new_val[ 1 ] = old_val[ 2 ];
  140.     new_val[ 2 ] = old_val[ 1 ];
  141.     new_val[ 3 ] = old_val[ 0 ];
  142.     memcpy( (char*)intel, (char*)new_val, 4 );
  143. }
  144.  
  145. // ----------------------------------------------------------------------------------------------------
  146.  
  147. void CDROM::read_sector( unsigned long sector, unsigned char _far* buffer )
  148. {
  149.     short hi_sector, lo_sector;
  150.     short hi_buffer, lo_buffer;
  151.  
  152.     lo_sector = (short)(sector & 0xffff);
  153.     hi_sector = (short)((sector >> 16) & 0xffff);
  154.  
  155.     lo_buffer = (short)((unsigned long)buffer & 0xffff);
  156.     hi_buffer = (short)(((unsigned long)buffer >> 16) & 0xffff);
  157.  
  158.     _asm {
  159.         mov ax,0x1500
  160.         int 0x2f
  161.  
  162.         mov ax,0x1508
  163.         mov dx,0x0001
  164.         mov si,hi_sector
  165.         mov di,lo_sector
  166.         mov bx, hi_buffer
  167.         mov es,bx
  168.         mov bx, lo_buffer
  169.         int 0x2f
  170.     };
  171. }
  172.  
  173. // ----------------------------------------------------------------------------------------------------
  174.  
  175. void CDROM::read_voldesc( unsigned char _far* buffer )
  176. {
  177.     short hi_buffer, lo_buffer;
  178.  
  179.     lo_buffer = (short)((unsigned long)buffer & 0xffff);
  180.     hi_buffer = (short)(((unsigned long)buffer >> 16) & 0xffff);
  181.  
  182.     _asm {
  183.         mov ax,0x1500
  184.         int 0x2f
  185.  
  186.         mov ax,0x1505
  187.         mov dx,0x0001
  188.         mov bx, hi_buffer
  189.         mov es,bx
  190.         mov bx, lo_buffer
  191.         int 0x2f
  192.     };
  193. }
  194.  
  195. // ----------------------------------------------------------------------------------------------------
  196.  
  197. void CDROM::make_string( char _far* string_in, int length )
  198. {
  199.     int pos;
  200.     for ( pos = length; (pos > -1) && (string_in[ pos ] == ' '); pos --)
  201.         string_in[ pos ] = '\0';
  202.         
  203.     for ( pos = 0; string_in[ pos ] != '\0'; pos++ )
  204.         if (string_in[ pos ] == ';')
  205.             string_in[ pos ] = '\0';
  206. }
  207.  
  208. // ----------------------------------------------------------------------------------------------------
  209.  
  210. class volume : public CDROM {
  211.     unsigned char _far* buffer;
  212.     prim_vol_desc _far* vol_desc;
  213.  
  214. public:
  215.     volume();
  216.     ~volume();
  217.  
  218.     void show( void );
  219.  
  220.     unsigned long root_sector( void ) { return (vol_desc->root.loc_extentI); }
  221.     unsigned long root_length( void ) { return (vol_desc->root.data_lenI);   }
  222.     int type( void )                  { return vol_desc->type;               }         
  223.     
  224.     const char _far* get_std_ident( void ) { return &vol_desc->id[ 0 ];        }
  225.     const char _far* system_id( void )     { return &vol_desc->system_id[ 0 ]; }
  226.     const char _far* volume_id( void )     { return &vol_desc->volume_id[ 0 ]; }
  227. };
  228.  
  229. // ----------------------------------------------------------------------------------------------------
  230.  
  231. volume::volume()
  232. {
  233.     buffer = new unsigned char[ buffer_length ];
  234.     vol_desc = (prim_vol_desc _far*)buffer;
  235.     read_voldesc( buffer );
  236. //    read_sector( 16, buffer );
  237.  
  238. //    motorola_to_intel( &vol_desc->root.loc_extentM, &vol_desc->root.loc_extentI );
  239. //    motorola_to_intel( &vol_desc->root.data_lenM, &vol_desc->root.data_lenI );
  240.     
  241.     make_string( &vol_desc->system_id[ 0 ],         32 );
  242.     make_string( &vol_desc->volume_id[ 0 ],         32 );
  243.     make_string( &vol_desc->volume_set_id[ 0 ],    128 );
  244.     make_string( &vol_desc->publisher_id[ 0 ],     128 );
  245.     make_string( &vol_desc->data_preparer[ 0 ],    128 );
  246.     make_string( &vol_desc->application_id[ 0 ],   128 );
  247.     make_string( &vol_desc->copyright[ 0 ],         37 );
  248.     make_string( &vol_desc->abstract_file_id[ 0 ],  37 );
  249.     make_string( &vol_desc->bibliographic_id[ 0 ],  37 );
  250. }
  251.  
  252. // ----------------------------------------------------------------------------------------------------
  253.  
  254. volume::~volume()
  255. {
  256.     delete[] buffer;
  257. }
  258.  
  259. // ----------------------------------------------------------------------------------------------------
  260.  
  261. void volume::show( void )
  262. {
  263.     printf( "\n");
  264.     printf( "Volume Descriptor Type:          %d\n", (int) vol_desc->type );
  265.     printf( "Standard Identifier:             %s\n", (char *)vol_desc->id );
  266.     printf( "Volume Descriptor Version:       %d\n", (int) vol_desc->version );
  267.     printf( "System Identifier:               %s\n", (char *)vol_desc->system_id );
  268.     printf( "Volume Identifier:               %s\n", (char *)vol_desc->volume_id );
  269.     printf( "Volume Space Size:               %d\n", vol_desc->space_size_i );
  270.     printf( "Volume Set Size:                 %d\n", vol_desc->set_size_i );
  271.     printf( "Volume Sequence Number:          %d\n", vol_desc->sequence_i );
  272.     printf( "Logical Block Size:              %d\n", vol_desc->block_size_i );
  273.     printf( "Path Table Size:                 %d\n", vol_desc->path_size_i );
  274.     printf( "Location of Occ of M Path Table: %d\n", vol_desc->i_table ); 
  275.     printf( "Location of Occ of Opt M Path T: %d\n", vol_desc->opt_i_table );
  276.     printf( "Volume Set Identifier:           %s\n", (char *)vol_desc->volume_set_id );  
  277.     printf( "Publisher Identifier:            %s\n", (char *)vol_desc->publisher_id ); 
  278.     printf( "Data Preparer Identifier:        %s\n", (char *)vol_desc->data_preparer );
  279.     printf( "Application Identifier:          %s\n", (char *)vol_desc->application_id );
  280.     printf( "Copyright File Identifier:       %s\n", (char *)vol_desc->copyright );
  281.     printf( "Abstract File Identifier:        %s\n", (char *)vol_desc->abstract_file_id );
  282.     printf( "Bibliographic File Identifier:   %s\n", (char *)vol_desc->bibliographic_id );
  283.     printf( "File Structure Version:          %d\n", (int) vol_desc->file_structure_version );
  284. //    printf( "\nROOT DIRECTORY RECORD:\n";
  285. }
  286.  
  287. // ----------------------------------------------------------------------------------------------------
  288. const int SHORT  = 0;
  289. const int LONG   = 1;
  290. const int NORMAL = 2;
  291.  
  292. class directory : public CDROM {
  293. private:
  294.     unsigned long start_sector;
  295.     unsigned long current_sector;
  296.     unsigned long length;
  297.     unsigned long overall_pos;
  298.     short buf_pos;
  299.  
  300.     char* name;
  301.  
  302.     unsigned char _far* dir_buffer;
  303.     unsigned char       file_buffer[ buffer_length ];
  304.     short dir_pos;
  305.     
  306.     dir_entry file;
  307.     
  308.     void to_start_dir_entry( void );
  309.     int  get_next_dir_entry( void );
  310.  
  311.     char* wild_card;
  312.     int wild_card_cmp( char* string, char* wild );
  313.  
  314.     void show_flags( void );
  315.     
  316.     int is_directory( void )  { return (file.file_flags_iso & 0x02);  }
  317.     int is_file( void )       { return !(file.file_flags_iso & 0xff); }
  318.  
  319.     void show_long_entry( void );
  320.     void show_short_entry( void );
  321.     void show_normal( void );
  322.     
  323.     int display_file( void );
  324.     int grab_file( int interactive = 0 );
  325.     
  326. public:
  327.     directory( char* old_name, char* dir_name, unsigned long dir_sector, unsigned long dir_length );
  328.     directory( volume& CDROM_vol );
  329.     directory::~directory();
  330.     
  331.     dir_entry* find_first( char* search );
  332.     dir_entry* find_next( void );
  333.     
  334.     char* get_name( void )   { return name; }
  335.  
  336.     void show_directory( char* search, int long_dir = NORMAL );
  337.     
  338.     directory* change_dir( char* dir_name );
  339.     
  340.     void show_file( char* filename );
  341.     
  342.     void get_file( char* filename, int interactive );
  343. };
  344.  
  345. // ----------------------------------------------------------------------------------------------------
  346.  
  347. volume primary_VTOC;
  348.  
  349. directory* root;
  350. directory* current_dir;
  351.  
  352. // ----------------------------------------------------------------------------------------------------
  353.  
  354. directory::directory(    char* old_name, char* dir_name,
  355.                         unsigned long dir_sector, unsigned long dir_length )
  356. {
  357.     current_sector = start_sector = dir_sector;
  358.     length = dir_length;
  359.     name = new char[ strlen( old_name ) + strlen( dir_name ) + 3 ];
  360.     wild_card = NULL;
  361.     name[ 0 ] = '\0';
  362.     
  363.     if (!strcmp( dir_name, "." ))
  364.         strcpy( name, old_name );
  365.     else if (!strcmp( dir_name, ".."))
  366.     {
  367.         int found = 0;
  368.         strcpy( name, old_name );
  369.         for (int i = strlen( name ); (i > 0) && !found; i--)
  370.         {
  371.             if (name[ i ] == '\\')
  372.                 found = 1;
  373.             name[ i ] = '\0';
  374.         }
  375.     }
  376.     else if (!strcmp( old_name, "\\" ))
  377.     {
  378.            strcpy( name, "\\" );
  379.         strcat( name, dir_name );
  380.     }
  381.     else
  382.     {
  383.         strcpy( name, old_name );
  384.            strcat( name, "\\" );
  385.         strcat( name, dir_name );
  386.     }
  387.     
  388.     dir_buffer  = new unsigned char[ 2048 ];
  389.  
  390.     to_start_dir_entry();
  391. }
  392.  
  393. // ----------------------------------------------------------------------------------------------------
  394.  
  395. directory::directory( volume& CDROM_vol )
  396. {
  397.     current_sector = start_sector = CDROM_vol.root_sector();
  398.     length = CDROM_vol.root_length();
  399.     wild_card = NULL;
  400.     name = new char[ 3 ];
  401.     strcpy( name , "\\" );
  402.     
  403.     dir_buffer  = new unsigned char[ 2048 ];
  404.  
  405.     to_start_dir_entry();
  406. }
  407.  
  408. // ----------------------------------------------------------------------------------------------------
  409.  
  410. directory::~directory()
  411. {
  412.     if (name)
  413.         delete[] name;
  414.  
  415.     if (wild_card)
  416.         delete[] wild_card;
  417.  
  418.     delete[] dir_buffer;
  419. }
  420.  
  421. // ----------------------------------------------------------------------------------------------------
  422.  
  423. directory* directory::change_dir( char* dir_name )
  424. {
  425.     char* name;
  426.     char* rest;
  427.     int   found = 0;
  428.     
  429.     name = dir_name;
  430.     rest = NULL;
  431.  
  432.     for (char* pos = name; !found & (*pos !='\0'); pos++)
  433.         if (*pos =='\\')
  434.         {
  435.             rest  = pos + 1;
  436.             *pos  = '\0';
  437.             found = 1;
  438.         }
  439.     if (strlen( name ) == 0)
  440.     {
  441.         directory* new_dir;
  442.         new_dir = new directory( primary_VTOC );
  443.         delete current_dir;
  444.         current_dir = new_dir;
  445.     }
  446.     else if (find_first( name ))
  447.     {
  448.         directory* new_dir;
  449.         new_dir = new directory( current_dir->name, (char*)file.file_id, file.loc_extentI, file.data_lenI );
  450.         delete current_dir;
  451.         current_dir = new_dir;
  452.     }
  453.     else
  454.         return NULL;
  455.  
  456.     if (rest != NULL)
  457.         return current_dir->change_dir( rest );
  458.     else
  459.         return current_dir;
  460. }
  461.  
  462. // ----------------------------------------------------------------------------------------------------
  463.  
  464. int directory::display_file( void )
  465. {   
  466.     char ans;
  467.     if (is_file())
  468.     {
  469.         printf( "Do you wish to view [%s] (Y/N/A) ?\n", file.file_id );
  470.     
  471.         ans = _getch();
  472.         if ((ans == 'y') || (ans == 'Y'))
  473.         {
  474.             unsigned long sector      = file.loc_extentI;
  475.             unsigned long display_len = file.data_lenI;
  476.             int sector_pos = 0;
  477.             int lines = 0;
  478.         
  479.             read_sector( sector++, (unsigned char _far*)file_buffer );
  480.             while (display_len > 0)
  481.             {
  482.                 display_len--;
  483.                 printf( "%c", file_buffer[ sector_pos ] );
  484.  
  485.                 if (file_buffer[ sector_pos ] == '\n')
  486.                     lines++;
  487.     
  488.                 if (lines == max_lines)
  489.                 {
  490.                     lines = 0;
  491.                     printf( "Paused - Return to continue, Q to quit, A to abort all\n" );
  492.                     ans = _getch();
  493.                     if ((ans == 'q') || (ans == 'Q'))
  494.                         return 0;
  495.                     if ((ans == 'a') || (ans == 'A'))
  496.                         return 0;
  497.                     printf("\r");
  498.                 }
  499.  
  500.                 sector_pos++;
  501.                 if (sector_pos == 2048)
  502.                 {
  503.                     read_sector( sector++, (unsigned char _far*)file_buffer );
  504.                     sector_pos = 0;
  505.                 }
  506.             }
  507.             return 0;
  508.         }
  509.         else if ((ans == 'n') || (ans == 'N'))
  510.             return 0;
  511.         else
  512.             return 1;
  513.     }
  514.     else
  515.         return 0;
  516. }
  517.  
  518. // ----------------------------------------------------------------------------------------------------
  519.  
  520. void directory::show_file( char* filename )
  521. {
  522.     int aborted;
  523.  
  524.     if (find_first( filename ))
  525.         aborted = display_file();
  526.         
  527.         while (find_next() && !aborted)
  528.             aborted = display_file();
  529. }
  530.  
  531. // ----------------------------------------------------------------------------------------------------
  532.  
  533. int directory::grab_file( int interactive )
  534. {
  535.     FILE* out_file;
  536.     int length;
  537.     char new_filename[ 128 ];
  538.     char ans;
  539.     
  540.     if (interactive && is_file())
  541.     {
  542.         printf( "Do you wish to get [%s] (Y/N/A) ?\n", file.file_id );
  543.         ans = _getch();
  544.         
  545.         if ((ans == 'A') || (ans == 'a'))
  546.             return 1;
  547.     }
  548.     
  549.     if ((!interactive || (ans == 'y') || (ans == 'Y')) && is_file())
  550.     {
  551.         strcpy( new_filename, output_dir );
  552.         if (length = strlen( new_filename ))
  553.         {
  554.             if (new_filename[ length - 1 ] != '\\')
  555.                 strcat( new_filename, "\\" );
  556.         }
  557.         strcat( (char*)new_filename, (char*)file.file_id );
  558.     
  559.         if ((out_file = fopen( new_filename, "wb" )) == NULL)
  560.         {
  561.             strcpy( new_filename, output_dir );
  562.             if (length = strlen( new_filename ))
  563.             {
  564.                 if (new_filename[ length - 1 ] != '\\')
  565.                     strcat( new_filename, "\\" );
  566.             }
  567.             char temp_str[ 20 ];
  568.             sprintf( temp_str, "%08x.cdr", file_number++ );
  569.             strcat( (char*)new_filename, temp_str );
  570.             out_file = fopen( new_filename, "wb" );
  571.         }
  572.         
  573.         if (out_file != NULL)
  574.         {
  575.             unsigned long file_length = file.data_lenI;
  576.             unsigned long sector = file.loc_extentI;
  577.     
  578.             printf( "Writing file %s to %s %lu bytes\n", file.file_id, new_filename, file_length );
  579.         
  580.             while (file_length)
  581.             {
  582.                 int block_size;
  583.     
  584.                 if (file_length >= 2048 )
  585.                     block_size = 2048;
  586.                 else
  587.                     block_size = file_length;
  588.     
  589.                 read_sector( sector++, file_buffer );
  590.                 fwrite( file_buffer, 1, (size_t)block_size, out_file );
  591.                 file_length -= block_size;
  592.             }
  593.             fclose( out_file );
  594.         }
  595.         else
  596.             printf( "Failed to write %s\n", new_filename );
  597.     }
  598.     
  599.     return 0;
  600. }
  601.  
  602. // ----------------------------------------------------------------------------------------------------
  603.  
  604. void directory::get_file( char* filename, int interactive )
  605. {
  606.     int aborted;
  607.  
  608.     if (find_first( filename ))
  609.         aborted = grab_file( interactive );
  610.         
  611.         while (find_next() && !aborted)
  612.             aborted = grab_file( interactive );
  613. }
  614.  
  615. // ----------------------------------------------------------------------------------------------------
  616.  
  617. void directory::show_long_entry( void )
  618. {
  619.     printf( "File Identifier:             %s\n", file.file_id );
  620.     printf( "Data Length:                 %lu\n", file.data_lenI  );
  621.     printf( "File Identifier Length:      %d\n", (int)file.len_fi );
  622.     printf( "Extended Attr Record Length: %u\n", (int) file.XAR_len );
  623.     printf( "Location of Extent:          %lu\n", file.loc_extentI );
  624.     printf( "Recording Date and Time:     %02d.%02d.19%02d %02d:%02d:%02d\n",
  625.             (int) file.record_time[ 2 ], (int) file.record_time[ 1 ], (int) file.record_time[ 0 ],
  626.             (int) file.record_time[ 3 ], (int) file.record_time[ 4 ], (int) file.record_time[ 5 ] );
  627.     printf( "Flags:                       (%d ", (int) file.file_flags_iso );
  628.     
  629.     show_flags();
  630.     
  631.     printf( ")\n\n" );
  632. }
  633.  
  634. // ----------------------------------------------------------------------------------------------------
  635.  
  636. void directory::show_short_entry( void )
  637. {
  638.     show_flags();
  639.  
  640.     printf( " %12lu ", file.data_lenI );
  641.     printf( "%02d.%02d.19%02d %02d:%02d:%02d  ",
  642.             (int) file.record_time[ 2 ], (int) file.record_time[ 1 ], (int) file.record_time[ 0 ],
  643.             (int) file.record_time[ 3 ], (int) file.record_time[ 4 ], (int) file.record_time[ 5 ] );
  644.     printf( " %s\n" , file.file_id );
  645. }
  646.  
  647.  
  648. // ----------------------------------------------------------------------------------------------------
  649.  
  650. void directory::show_normal( void )
  651. {
  652.     if (is_file())
  653.         printf( "%-32s  ", file.file_id );
  654.     else
  655.         printf( "%%%-32s ", file.file_id );
  656. }
  657.  
  658. // ----------------------------------------------------------------------------------------------------
  659.  
  660. void directory::show_flags( void )
  661. {
  662.     if (file.file_flags_iso == 0)
  663.         printf( "file " );
  664.  
  665.     if (file.file_flags_iso & 1)
  666.         printf( "existence " );
  667.  
  668.     if (file.file_flags_iso & 2)
  669.         printf( "dir  " );
  670.  
  671.     if (file.file_flags_iso & 4)
  672.         printf( "associated " );
  673.  
  674.     if (file.file_flags_iso & 8)
  675.         printf( "record " );
  676.  
  677.     if (file.file_flags_iso & 16)
  678.         printf( "protection " );
  679.  
  680.     if (file.file_flags_iso & 128)
  681.         printf( "multi-extent " );
  682. }
  683.  
  684. // ----------------------------------------------------------------------------------------------------
  685.  
  686. void directory::show_directory( char* search, int long_dir )
  687. {
  688.     int finished = 0;
  689.     int lines = 0;
  690.     int column = 0;
  691.     char ans;
  692.  
  693.     if (find_first( search ))
  694.     {
  695.         if (long_dir == LONG)
  696.         {
  697.             show_long_entry();
  698.             lines = 1;
  699.         }
  700.         else if (long_dir == SHORT)
  701.         {
  702.             show_short_entry();
  703.             lines = 1;
  704.         }
  705.         else
  706.         {
  707.             show_normal();
  708.             column = 1;
  709.             lines = 0;
  710.         }
  711.  
  712.         while (find_next() && !finished)
  713.         {
  714.             if (long_dir == LONG)
  715.             {
  716.                 show_long_entry();
  717.                 lines++;
  718.             }
  719.             else if (long_dir == SHORT)
  720.             {
  721.                 show_short_entry();
  722.                 lines++;
  723.             }
  724.             else
  725.             {
  726.                 show_normal();
  727.                 column++;
  728.                 
  729.                 if (column >= 2)
  730.                 {
  731.                     column = 0;
  732.                     lines++;
  733.                     printf( "\n" );
  734.                 }
  735.             }
  736.  
  737.             if (lines == max_lines)
  738.             {
  739.                     lines = 0;
  740.                     printf( "Paused - Return to continue, Q to quit\n" );
  741.                     ans = _getch();
  742.                     if ((ans == 'q') || (ans == 'Q'))
  743.                         finished = 1;
  744.                     printf("\r");
  745.             }
  746.         }
  747.  
  748.         if (long_dir == NORMAL)
  749.             if (column)
  750.                 printf("\n");
  751.     }
  752. }
  753.  
  754. // ----------------------------------------------------------------------------------------------------
  755.  
  756. void directory::to_start_dir_entry( void )
  757. {
  758.     buf_pos        = 0;
  759.     overall_pos    = 0;
  760.     current_sector = start_sector;
  761.     read_sector( start_sector, dir_buffer );
  762. }
  763.  
  764. // ----------------------------------------------------------------------------------------------------
  765. // Gets the next directory entry in the list, and sets file to point to it.
  766. // Returns a 1 if another entry was found otherwise it returns a 0
  767.  
  768. int directory::get_next_dir_entry( void )
  769. {
  770.     if (overall_pos < length)
  771.     {
  772.         if (buf_pos >= buffer_length)
  773.         {
  774.             buf_pos = 0;
  775.             current_sector++;
  776.             read_sector( current_sector, dir_buffer );
  777.         }
  778.         
  779.         memcpy( &file, (dir_entry *)&dir_buffer[ buf_pos ], sizeof(dir_entry) );
  780.         file.file_id[ file.len_fi ] = '\0';
  781.         make_string( (char *)file.file_id, file.len_fi );
  782.  
  783.         if (file.file_id[ 0 ] == 0)
  784.         {
  785.             strcpy( (char *)file.file_id, "." );
  786.             file.len_fi = 1;
  787.             if ((file.loc_extentI != start_sector) && (file.len_dr))
  788.                 return 0;
  789.         }
  790.         else if (file.file_id[ 0 ] == 1)
  791.         {
  792.             strcpy( (char *)file.file_id, ".." );
  793.             file.len_fi = 2;
  794.             if (file.len_dr == 0)
  795.                 file.len_dr = 34;
  796.         }
  797.  
  798.         buf_pos     += file.len_dr;
  799.         overall_pos += file.len_dr;
  800.  
  801. //        if (file.loc_extentI == 0)
  802. //        {
  803. //            buf_pos = 2048;
  804. //            return get_next_dir_entry();
  805. //        }
  806. //        else 
  807.         if (file.len_dr == 0)
  808.         {
  809.             if (file.loc_extentI == start_sector)
  810.                 return 0;
  811.             else
  812.             {
  813.                 buf_pos = 2048;
  814.                 return get_next_dir_entry();
  815.             }
  816.         }
  817.         else
  818.             return 1;
  819.     }
  820.     else
  821.         return 0;
  822. }
  823.  
  824. // ----------------------------------------------------------------------------------------------------
  825.  
  826. dir_entry* directory::find_first( char* search_name )
  827. {
  828.     if (wild_card)
  829.         delete[] wild_card;
  830.         
  831.     wild_card = new char[ strlen( search_name ) + 1 ];
  832.     strcpy( wild_card, search_name );
  833.     to_start_dir_entry();
  834.     return find_next();
  835. }
  836.  
  837. // ----------------------------------------------------------------------------------------------------
  838.  
  839. dir_entry* directory::find_next( void )
  840. {
  841.     int found = 0;
  842.     int no_more = 0;
  843.  
  844.     while (!found && !no_more)
  845.     {
  846.         no_more = !get_next_dir_entry();
  847.         found = wild_card_cmp( (char *)file.file_id, wild_card );
  848.     }
  849.  
  850.     if (no_more)
  851.         return NULL;
  852.     else
  853.         return &file;
  854. }
  855.  
  856. // ----------------------------------------------------------------------------------------------------
  857. // Someday I will have to re-write this!
  858.  
  859. int directory::wild_card_cmp( char* string, char* wild )
  860. {
  861.     int   match     = TRUE;
  862.     int   finished  = FALSE;
  863.     char  *str_pos  = string;
  864.     char  *wild_pos = wild;
  865.  
  866.     if ((*str_pos != '\0') || (*wild_pos != '\0'))
  867.     {
  868.         do {
  869.             switch (*wild_pos)
  870.             {
  871.             case '*':
  872.                 while ((*wild_pos != '\0') && ((*wild_pos == '?') || (*wild_pos == '*')))
  873.                     wild_pos++;
  874.  
  875.                 if (*wild_pos != '\0')
  876.                 {
  877.                     do {
  878.                         if (!match)
  879.                             str_pos++;
  880.  
  881.                         while ((*str_pos != '\0') && (tolower(*str_pos) != tolower(*wild_pos)))
  882.                             str_pos++;
  883.  
  884.                         match = wild_card_cmp( str_pos, wild_pos );
  885.  
  886.                     } while (!match && (*str_pos != '\0'));
  887.  
  888.                     finished = match;
  889.                 }
  890.                 else
  891.                     finished = TRUE;
  892.                 break;
  893.           
  894.             case '?':
  895.                 str_pos++;
  896.                 wild_pos++;
  897.                 break;
  898.           
  899.             default:
  900.                 if (tolower( *str_pos ) == tolower( *wild_pos ))
  901.                 {
  902.                     str_pos++;
  903.                     wild_pos++;
  904.                 }
  905.                 else
  906.                     match = FALSE;
  907.                 break;
  908.             }
  909.         } while ((*str_pos != '\0') && (*wild_pos != '\0') && match && !finished);
  910.  
  911.         if ((*str_pos == '\0') && (*wild_pos !='\0'))
  912.             while ((*wild_pos != '\0') && (*wild_pos == '*'))
  913.                 wild_pos++;
  914.  
  915.         if (!finished && ((*wild_pos != '\0') || (*str_pos != '\0')))
  916.             match = FALSE;
  917.     }
  918.     else
  919.         match = FALSE;
  920.  
  921.     return match;
  922. }
  923.  
  924. /* ----------------------------------------------------------------------- */
  925.  
  926. void  show_copyright( void )
  927. {
  928.     puts("\nGo Fishing, Version 1.1");
  929.     puts("  AMIGA CDROM handler for MS-DOS");
  930.     puts("  (c) 1995 N. A. Balharrie\n");
  931. }
  932.  
  933. // ----------------------------------------------------------------------------------------------------
  934.  
  935. int  command_line ( char *cmd_line )
  936. {
  937.     char command[ 256 ];
  938.     char parameter[ 256 ];
  939.     
  940.     int finished = FALSE;
  941.     
  942.     if (strlen(cmd_line))
  943.     {
  944.         command[ 0 ] = '\0';
  945.         parameter[ 0 ] = '\0';
  946.  
  947.         sscanf( cmd_line, "%s %s", command, parameter );
  948.     
  949.         if ((!strcmp("quit", command )) || (!strcmp("lo", command )))
  950.             finished = TRUE;
  951.  
  952. //        else if (!strcmp( "r", command ))
  953. //            list_rec( &curr_dir );
  954.  
  955.         else if (!strcmp( "voldesc", command))
  956.             primary_VTOC.show();
  957.     
  958.         else if (!strcmp( "ls", command ))
  959.             if (parameter[ 0 ] == '\0')
  960.                 current_dir->show_directory( "*", NORMAL );
  961.             else
  962.                 current_dir->show_directory( parameter, NORMAL );
  963.                                                                
  964.         else if (!strcmp( "ex", command ))
  965.             current_dir->show_directory( parameter, LONG );
  966.  
  967.         else if (!strcmp( "ll", command ))
  968.             if (parameter[ 0 ] == '\0')
  969.                 current_dir->show_directory( "*", SHORT );
  970.             else
  971.                 current_dir->show_directory( parameter, SHORT );
  972.     
  973.         else if (!strcmp( "cd", command ))
  974.         {
  975.             if (current_dir->change_dir( parameter ) == NULL)
  976.                 printf( "No such directory\n" );
  977.         }
  978.     
  979.         else if (!strcmp( "pod", command ))
  980.             printf("%s\n", output_dir );
  981.     
  982.         else if (!strcmp( "cod", command ))
  983.         {
  984.             delete[] output_dir;
  985.             output_dir = new char[ strlen( parameter ) + 1 ];
  986.             strcpy( output_dir, parameter );
  987.         }
  988.         
  989.         else if (!strcmp( "more", command) || !strcmp( "m", command))
  990.             current_dir->show_file( parameter );
  991.  
  992.         else if (!strcmp( "get", command ))
  993.             current_dir->get_file( parameter, 0  );
  994.  
  995.         else if (!strcmp( "iget", command ))
  996.             current_dir->get_file( parameter, 1  );
  997.  
  998. //        else if (!strcmp( "exec", command ))
  999. //            exec_cmd( cmd_line );
  1000.  
  1001.         else if (!strcmp( "?", command ) || !strcmp( "help", command ))
  1002.         {
  1003.             show_copyright();
  1004.             puts( "Available commands\n" );
  1005.             puts( "quit       - Quit the program" );
  1006.             puts( "voldesc    - Display the CDROM descriptor");
  1007.             puts( "ls         - List directory" );
  1008.             puts( "ll         - Detailed directory list" );
  1009.             puts( "cd dir     - Change to the `dir' directory" );
  1010.             puts( "cod dir    - Change the current output directory to be `dir'" );
  1011.             puts( "             (must include the final /,  ie. /etc/ )" );
  1012.             puts( "pod        - Display the current output directory" );
  1013.             puts( "get file   - Get the specified file and place it in the 'cod'" );
  1014.             puts( "iget file  - Interactively get the specified file and place it in the 'cod'" );
  1015.             puts( "more file  - Display `file' on the terminal");
  1016.             puts( "m file     - Shorthand for more" );
  1017.             puts( "exec file  - Execut the script file `file'" );
  1018.             puts( "" );
  1019.         }
  1020.         else
  1021.             printf("%s is not recognised as a command.\n", command );
  1022.     }
  1023.     return finished;
  1024. }
  1025.  
  1026. // ----------------------------------------------------------------------------------------------------
  1027.  
  1028. void  main( void  )
  1029. {
  1030.     char  cmd_line[ 256 ];
  1031.  
  1032.     root = new directory( primary_VTOC );
  1033.     current_dir = root;
  1034.  
  1035.     output_dir = new char[ 2 ];
  1036.     output_dir[ 0 ] = '\\';
  1037.     output_dir[ 1 ] = '\0';
  1038.     
  1039.     show_copyright();
  1040.  
  1041. //    exec_script( "fish-init", 0 );
  1042.     puts( "Type help or ? for a list of the commands\n" );
  1043.         
  1044.     do {
  1045.         printf("%s %% ", current_dir->get_name() );
  1046.         gets( cmd_line );
  1047.     } while ( !command_line( cmd_line ) );
  1048.  
  1049.     delete root;
  1050.     delete[] output_dir;
  1051. }
  1052.