home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / lha100bt.zip / lha-1.00 / src / lharc.c < prev    next >
C/C++ Source or Header  |  1994-09-08  |  26KB  |  1,182 lines

  1.  
  2. /*----------------------------------------------------------------------*/
  3. /*        LHarc Archiver Driver for UNIX                */
  4. /*        This is part of LHarc UNIX Archiver Driver        */
  5. /*                                    */
  6. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  7. /*        Thanks to H.Yoshizaki. (MS-DOS LHarc)            */
  8. /*                                    */
  9. /*  V0.00  Original                1988.05.23  Y.Tagawa    */
  10. /*  V0.01  Alpha Version (for 4.2BSD)        1989.05.28  Y.Tagawa    */
  11. /*  V0.02  Alpha Version Rel.2            1989.05.29  Y.Tagawa    */
  12. /*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa    */
  13. /*  V0.03a Debug                1989.07.03  Y.Tagawa    */
  14. /*  V0.03b Modified                1989.07.13  Y.Tagawa    */
  15. /*  V0.03c Debug (Thanks to void@rena.dit.junet)1989.08.09  Y.Tagawa    */
  16. /*  V0.03d Modified (quiet and verbose)        1989.09.14  Y.Tagawa    */
  17. /*  V1.00  Fixed                1989.09.22  Y.Tagawa    */
  18. /*  V1.01  Bug Fixed                1989.12.25  Y.Tagawa    */
  19. /*                                    */
  20. /*  DOS-Version Original LHx V C2.01         (C) H.Yohizaki        */
  21. /*                                    */
  22. /*  V2.00  UNIX Lharc + DOS LHx -> OSK LHx    1990.11.01  Momozou    */
  23. /*  V2.01  Minor Modified            1990.11.24  Momozou    */
  24. /*                                    */
  25. /*  V0.02  LHx for UNIX                1991.11.18  M.Oki    */
  26. /*  V0.03  LHa for UNIX                1991.12.17  M.Oki    */
  27. /*  V0.04  LHa for UNIX    beta version        1992.01.20  M.Oki    */
  28. /*  V1.00  LHa for UNIX    Fixed            1992.03.19  M.Oki    */
  29.  
  30. /*  V1.01  LHa for OS2    Modified        1994.08.31 Enrico Demarin    */
  31.  
  32. /*----------------------------------------------------------------------*/
  33.  
  34. #include "lharc.h"
  35.  
  36. /*****************************************
  37. Added 31-8-1994     by Enrico Demarin 
  38. ******************************************/
  39.  
  40. #define INCL_DOS
  41. #define INCL_ERRORS
  42. #include <os2emx.h>
  43. #include <stdlib.h>
  44. #include <malloc.h>
  45.  
  46. /*****************************************/
  47.  
  48. /*----------------------------------------------------------------------*/
  49. /*                PROGRAM                 */
  50. /*----------------------------------------------------------------------*/
  51.  
  52.  
  53. #define CMD_UNKNOWN    0
  54. #define CMD_EXTRACT    1
  55. #define CMD_ADD        2
  56. #define CMD_LIST    3
  57. #define CMD_DELETE    4
  58.  
  59. static int    cmd = CMD_UNKNOWN;
  60. char    **cmd_filev;
  61. int    cmd_filec;
  62.  
  63. char    *archive_name="";
  64. char    expanded_archive_name[FILENAME_LENGTH];
  65. char    temporary_name[FILENAME_LENGTH];
  66. char    backup_archive_name[FILENAME_LENGTH];
  67.  
  68. /* static functions */
  69. static void sort_files();
  70.  
  71. /*****************************************
  72.  
  73. Added  31-8-1994 by Enrico Demarin
  74.  
  75. Include SYSTEM and HIDDEN files ?
  76. Recurse subdirectories ?
  77.  
  78. ******************************************/
  79. void     convert_slash(char *);
  80. int      expand_wildcards(char *,char *);
  81.  
  82. boolean recurse_subdirs = FALSE;
  83. boolean make_backups = FALSE;
  84. int file_mask = FILE_DIRECTORY | FILE_ARCHIVED | FILE_READONLY;
  85.  
  86. /*****************************************/
  87.  
  88. /* options */
  89. boolean    quiet = FALSE;
  90. boolean    text_mode = FALSE;
  91. boolean    verbose = FALSE;
  92. boolean    noexec = FALSE;    /* debugging option */
  93. boolean    force = FALSE;
  94. boolean    prof = FALSE;
  95. int compress_method = 5;    /* deafult -lh5- */
  96. int header_level = HEADER_LEVEL1;
  97. #ifdef EUC
  98. boolean euc_mode = FALSE;
  99. #endif
  100.  
  101. /* view command flags */
  102. boolean    verbose_listing = FALSE;
  103.  
  104. /* extract command flags */
  105. boolean    output_to_stdout = FALSE;
  106.  
  107. /* append command flags */
  108. boolean    new_archive = FALSE;
  109. boolean    update_if_newer = FALSE;
  110. boolean    delete_after_append = FALSE;
  111. boolean    generic_format = FALSE;
  112.  
  113. boolean    remove_temporary_at_error = FALSE;
  114. boolean    recover_archive_when_interrupt = FALSE;
  115. boolean    remove_extracting_file_when_interrupt = FALSE;
  116. boolean get_filename_from_stdin = FALSE;
  117. boolean ignore_directory = FALSE;
  118. boolean verify_mode = FALSE;
  119.  
  120.  
  121.  
  122. char *extract_directory = NULL;
  123. char **xfilev;
  124. int  xfilec = 257;
  125. char name[CCHMAXPATH];
  126. char *nameptr;                 
  127. int res;
  128.  
  129. /*----------------------------------------------------------------------*/
  130. /* NOTES :        Text File Format                */
  131. /*    GENERATOR        NewLine                    */
  132. /*    [generic]        0D 0A                    */
  133. /*    [MS-DOS]        0D 0A                    */
  134. /*    [OS9][MacOS]        0D                    */
  135. /*    [UNIX]            0A                    */
  136. /*----------------------------------------------------------------------*/
  137.  
  138.  
  139. static void
  140. print_tiny_usage_and_exit ()
  141. {
  142.   fprintf(stderr, "Usage: lha [-]{axelvudmcpRBSH}[qvnfodizg012][w=<dir>] archive_file [file...]\n\n\
  143. Commands:                           options:\n\
  144.  a   Add(or replace) to archive      q  quiet\n\
  145.  x,e EXtract from archive            v  verbose\n\
  146.  l,v List / Verbose List             n  not execute\n\
  147.  u   Update newer files to archive   f  force (over write at extract)\n\
  148.  d   Delete from archive             t  FILES are TEXT file\n\
  149.  m   Move to archive (means 'ad')    o  use LHarc compatible method (a/u)\n\
  150.  c   re-Construct new archive        w=<dir> specify extract directory (x/e)\n\
  151.  p   Print to STDOUT from archive    d  delete FILES after (a/u/c)\n\
  152.  t   Test file CRC in archive        i  ignore directory path (x/e)\n\
  153.                                      z  files not compress (a/u)\n\
  154.                                      g  [Generic] format (for compatibility)\n\
  155.                                      0/1/2 header level (a/u)\n\
  156.                                      R   Recurse subdirs\n\
  157.                                      S   Include system files\n\
  158.                                      H   Include hidden files\n\
  159.                                      B   Make Backups
  160. ");                                    
  161. #ifdef EUC
  162.   fprintf (stderr, "\
  163.                                      e  TEXT code convert from/to EUC\n\
  164. ");
  165. #endif
  166.   exit (1);
  167. }
  168.  
  169. void
  170. main (argc, argv)
  171.      int argc;
  172.      char *argv[];
  173. {
  174.   char *p , inpbuf[256];
  175.   int i,filename_pos=1;
  176.  
  177.   fprintf (stderr, "Lha for OS/2 V1.00Beta 31-08-1994 by Enrico Demarin\n\n"); 
  178.  
  179.   
  180.   if (argc < 2)
  181.     print_tiny_usage_and_exit ();
  182.   if (argc < 3) {
  183.   /* archive file name */
  184.   archive_name = argv[1];
  185.   filename_pos = 1;
  186.     cmd = CMD_LIST;
  187.     goto work;
  188.   }
  189.   
  190.  
  191.   for (i=1; i<argc; i++)
  192.   {
  193.   
  194.   if ((cmd==CMD_UNKNOWN)&&(argv[i][0]!='-'))
  195.   {   
  196.   if (strlen(argv[i])>1)
  197.         { fprintf(stderr, "LHa: nothing to do !\n"); exit(1);  }
  198.      
  199.  
  200.   switch ( argv[i][0] )
  201.     {
  202.     case 'x':
  203.     case 'e':
  204.       cmd = CMD_EXTRACT;
  205.       break;
  206.  
  207.     case 'p':
  208.       output_to_stdout = TRUE;
  209.       cmd = CMD_EXTRACT;
  210.       break;
  211.  
  212.     case 'c':
  213.       new_archive = TRUE;
  214.       cmd = CMD_ADD;
  215.       break;
  216.  
  217.     case 'a':
  218.       cmd = CMD_ADD;
  219.       break;
  220.  
  221.     case 'd':
  222.       cmd = CMD_DELETE;
  223.       break;
  224.  
  225.     case 'u':
  226.       update_if_newer = TRUE;
  227.       cmd = CMD_ADD;
  228.       break;
  229.  
  230.     case 'm':
  231.       delete_after_append = TRUE;
  232.       cmd = CMD_ADD;
  233.       break;
  234.  
  235.     case 'v':
  236.       verbose_listing = TRUE;
  237.       cmd = CMD_LIST;
  238.       break;
  239.  
  240.     case 'l':
  241.       cmd = CMD_LIST;
  242.       break;
  243.  
  244.     case 't':
  245.       cmd = CMD_EXTRACT;
  246.       verify_mode = TRUE;
  247.       break;
  248.  
  249.     default:
  250.         print_tiny_usage_and_exit ();
  251.     
  252.     }
  253.     argv[i][0]=0;
  254.    }
  255.     else { 
  256.            if (argv[i][0]!='-')
  257.          { archive_name=argv[i]; filename_pos=i; break;   }
  258.         }
  259.  
  260.   }
  261.   
  262.   for (i=1; i<argc; i++)
  263.   { 
  264.   /* options */
  265.   p = &argv[i][1];
  266.   if (argv[i][0]=='-')
  267.   { 
  268.   for (p = &argv[i][1]; *p; )
  269.     {
  270.       switch ( (*p++) )
  271.     {
  272.  
  273.     case 'H':
  274.       file_mask|=FILE_HIDDEN;
  275.       break;
  276.     case 'S':
  277.       file_mask|=FILE_SYSTEM;
  278.       break;
  279.     case 'R':
  280.       recurse_subdirs=TRUE;
  281.       break;
  282.     case 'B':
  283.       make_backups=TRUE;
  284.       break;
  285.       
  286.        
  287.     
  288.         case 'q':    quiet = TRUE; break;
  289.         case 'f':    force = TRUE; break;
  290.         case 'p':    prof = TRUE; break;
  291.         case 'v':    verbose = TRUE; break;
  292.         case 't':    text_mode = TRUE; break;
  293. #ifdef EUC
  294.         case 'e':    text_mode = TRUE; euc_mode = TRUE; break;
  295. #endif
  296.         case 'n':    noexec = TRUE; break;
  297.         case 'g':    generic_format = TRUE; header_level = 0; break;
  298.         case 'd':    delete_after_append = TRUE; break;
  299.         case 'o':    compress_method = 1; header_level = 0; break;
  300.         case 'z':    compress_method = 0; break;
  301.         case 'i':    ignore_directory = TRUE; break;
  302.         case 'w':    if ( *p=='=' ) p++;
  303.                     extract_directory=p;
  304.                     while (*p) p++;
  305.                     break;
  306.         case '0':    header_level = HEADER_LEVEL0; break;
  307.         case '1':    header_level = HEADER_LEVEL1; break;
  308.         case '2':    header_level = HEADER_LEVEL2; break;
  309.         default:
  310.           fprintf(stderr, "LHa: Unknown option '%c'.\n", p[-1]);
  311.           exit(1);
  312.         }
  313.     }
  314.      }
  315.    }  
  316.  
  317. work:
  318.     
  319.    
  320.  
  321.  
  322.   if (!strcmp(archive_name, "-"))
  323.     {
  324.       if (!isatty(1) && cmd == CMD_ADD) quiet = TRUE;
  325.     }
  326.   else
  327.     {
  328.       if (argc == 3 && !isatty(0))
  329.     get_filename_from_stdin = TRUE;
  330.     }
  331.  
  332.   /* target file name */
  333.   if ( get_filename_from_stdin )
  334.   {
  335.       cmd_filec = 0;
  336.     if ( (xfilev = (char **)malloc(sizeof(char *) * xfilec)) == NULL)
  337.         fatal_error("Virtual memory exhausted\n");
  338.      while ( gets( inpbuf ) )
  339.      {
  340.         if ( cmd_filec >= xfilec )
  341.         {
  342.             xfilec += 256;
  343.             cmd_filev = (char **)realloc(xfilev,
  344.                           sizeof(char *) * xfilec);
  345.             if ( cmd_filev == NULL )
  346.                 fatal_error("Virtual memory exhausted\n");
  347.             xfilev = cmd_filev;
  348.         }                
  349.          if ( strlen( inpbuf )<1 ) continue;
  350.          if ( (xfilev[cmd_filec++]=(char *)strdup(inpbuf))==NULL )
  351.              fatal_error("Virtual memory exhausted\n");
  352.      }
  353.      xfilev[cmd_filec] = NULL;
  354.      cmd_filev = xfilev;
  355.   }
  356.   
  357.   else
  358.   {
  359.    int count;
  360. /*****************************************************
  361.  Added  31-8-1994 by Enrico Demarin
  362.  Wild card matching for OS-2
  363. ******************************************************/
  364.  
  365. if (cmd==CMD_ADD)
  366.  
  367.   
  368. cmd_filec = 0;
  369. cmd_filev = NULL;
  370.         
  371. for (count=filename_pos+1; count<argc; count++)
  372.  if ((argv[count][0])&&(argv[count][0]!='-'))
  373.  { 
  374.  nameptr=(char *)_getname(argv[count]);
  375.         
  376.  if (nameptr!=argv[count]) 
  377.   {
  378.    strcpy(name,nameptr);
  379.    *nameptr=0;
  380.    res=expand_wildcards(argv[count],name);
  381.   } else res=expand_wildcards(NULL,argv[count]);
  382.  if (!res) fatal_error("Virtual memory exhausted\n");
  383.  }
  384. }
  385.  }  else { 
  386.     cmd_filec = argc-filename_pos-1;
  387.     cmd_filev = argv+filename_pos+1;
  388.      }
  389.  
  390. }
  391.  
  392.              
  393. /*****************************************************/
  394.   sort_files ();
  395.  
  396.   /* make crc table */
  397.   make_crctable();
  398.  
  399.  
  400.  
  401.   switch (cmd)
  402.     {
  403.     case CMD_ADD:    cmd_add ();    break;
  404.     case CMD_DELETE:    cmd_delete ();    break;
  405.  
  406.     case CMD_EXTRACT:            /* Archive pattern matching */
  407.     case CMD_LIST:    
  408.     { 
  409.     HDIR handle = HDIR_CREATE;
  410.     static FILEFINDBUF3 ffbuf;
  411.     ULONG count = 1;
  412.     APIRET goon;
  413.     char *filter=archive_name;
  414.     
  415.  
  416.  
  417.     goon = DosFindFirst(filter, &handle,
  418.             0, (void *) &ffbuf, sizeof(ffbuf), &count, FIL_STANDARD);
  419.  
  420.     while (goon==NO_ERROR)
  421.     { 
  422.       fprintf (stderr, "Processing archive : %s\n", ffbuf.achName);
  423.       archive_name=ffbuf.achName;
  424.       
  425.       if (cmd=CMD_EXTRACT) 
  426.       cmd_extract (); else cmd_list ();    
  427.       
  428.       count = 1;
  429.       goon = DosFindNext(handle, &ffbuf, sizeof(ffbuf), &count);
  430.         
  431.       fprintf (stderr, "Done.\n\n", ffbuf.achName);
  432.     
  433.     }
  434.    
  435.    if (handle) DosFindClose(handle);
  436.      
  437.     } break;
  438.  
  439.  
  440.     }
  441.     
  442.  
  443. #ifdef USE_PROF
  444.   if (!prof)
  445.     exit (0);
  446. #endif
  447.  
  448.   exit (0);
  449. }
  450.  
  451. static void
  452. message_1 (title, subject, name)
  453.      char *title, *subject, *name;
  454. {
  455.   fprintf (stderr, "LHa: %s%s ", title, subject);
  456.   fflush (stderr);
  457.  
  458.   if (errno == 0)
  459.     fprintf (stderr, "%s\n", name);
  460.   else
  461.     perror (name);
  462. }
  463.  
  464. void
  465. message (subject, name)
  466.      char *subject, *name;
  467. {
  468.   message_1 ("", subject, name);
  469. }
  470.  
  471. void
  472. warning (subject, name)
  473.      char *subject, *name;
  474. {
  475.   message_1 ("Warning: ", subject, name);
  476. }
  477.  
  478. void
  479. error (subject, msg)
  480.      char *subject, *msg;
  481. {
  482.   message_1 ("Error: ", subject, msg);
  483. }
  484.  
  485. void
  486. fatal_error (msg)
  487.      char *msg;
  488. {
  489.   message_1 ("Fatal error:", "", msg);
  490.  
  491.   if (remove_temporary_at_error)
  492.     unlink (temporary_name);
  493.  
  494.   exit (1);
  495. }
  496.  
  497. char *writting_filename;
  498. char *reading_filename;
  499.  
  500. void
  501. write_error ()
  502. {
  503.   fatal_error (writting_filename);
  504. }
  505.  
  506. void
  507. read_error ()
  508. {
  509.   fatal_error (reading_filename);
  510. }
  511.  
  512. void
  513. interrupt (signo)
  514.      int signo;
  515. {
  516.   errno = 0;
  517.   message ("Interrupted\n", "");
  518.  
  519.   if ( temporary_fp ) fclose (temporary_fp);
  520.   unlink (temporary_name);
  521.   if (recover_archive_when_interrupt)
  522.     rename (backup_archive_name, archive_name);
  523.   if (remove_extracting_file_when_interrupt)
  524.     {
  525.       errno = 0;
  526.       message ("Removing", writting_filename);
  527.       unlink (writting_filename);
  528.     }
  529.   signal (SIGINT, SIG_DFL);
  530.   signal (SIGHUP, SIG_DFL);
  531.   kill (getpid (), signo);
  532. }
  533.  
  534.  
  535.  
  536. /*----------------------------------------------------------------------*/
  537. /*                                    */
  538. /*----------------------------------------------------------------------*/
  539.  
  540. static int
  541. sort_by_ascii (a, b)
  542.      char **a, **b;
  543. {
  544.   register char *p, *q;
  545.   register int c1, c2;
  546.  
  547.   p = *a, q = *b;
  548.   if (generic_format)
  549.     {
  550.       do
  551.     {
  552.       c1 = *(unsigned char*)p ++;
  553.       c2 = *(unsigned char*)q ++;
  554.       if (!c1 || !c2)
  555.         break;
  556.       if (islower (c1))
  557.         c1 = toupper (c1);
  558.       if (islower (c2))
  559.         c2 = toupper (c2);
  560.     }
  561.       while (c1 == c2) ;
  562.       return c1 - c2;
  563.     }
  564.   else
  565.     {
  566.       while (*p == *q && *p != '\0')
  567.     p ++, q ++;
  568.       return *(unsigned char*)p - *(unsigned char*)q;
  569.     }
  570. }
  571.  
  572. static void
  573. sort_files ()
  574. {
  575.   if (cmd_filec > 1)
  576.     qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
  577. }
  578.  
  579. char *xmalloc (size)
  580.      int size;
  581. {
  582.   char *p = (char *)malloc (size);
  583.   if (!p)
  584.     fatal_error ("Not enough memory");
  585.   return p;
  586. }
  587.  
  588. char *xrealloc (old, size)
  589.      char *old;
  590.      int size;
  591. {
  592.   char *p = (char *)realloc (old, size);
  593.   if (!p)
  594.     fatal_error ("Not enough memory");
  595.   return p;
  596. }
  597.  
  598. /*----------------------------------------------------------------------*/
  599. /*                STRING POOL                */
  600. /*----------------------------------------------------------------------*/
  601.  
  602. /*
  603.  * string pool :
  604.  *    +-------------+-------------+---     ---+-------------+----------+
  605.  *    | N A M E 1 \0| N A M E 2 \0|    ...    | N A M E n \0|             |
  606.  *    +-------------+-------------+---     ---+-------------+----------+
  607.  *    ^                              ^         ^
  608.  * buffer+0                        buffer+used  buffer+size
  609.  */
  610.  
  611. /*
  612.  * vector :
  613.  *    +---------------+---------------+-------------     -------------+
  614.  *    | pointer to    | pointer to    | pointer to   ...  pointer to    |
  615.  *    |  string pool    |  N A M E 1    |  N A M E 2   ...   N A M E n    |
  616.  *    +---------------+---------------+-------------     -------------+
  617.  *    ^        ^
  618.  *   malloc base      returned
  619.  */
  620.  
  621. void
  622. init_sp (sp)
  623.      struct string_pool *sp;
  624. {
  625.   sp->size = 1024 - 8;        /* any ( >=0 ) */
  626.   sp->used = 0;
  627.   sp->n = 0;
  628.   sp->buffer = (char*)xmalloc (sp->size * sizeof (char));
  629. }
  630.  
  631. void
  632. add_sp (sp, name, len)
  633.      struct string_pool *sp;
  634.      char *name;        /* stored '\0' at tail */
  635.      int len;            /* include '\0' */
  636. {
  637.   while (sp->used + len > sp->size)
  638.     {
  639.       sp->size *= 2;
  640.       sp->buffer = (char*) xrealloc (sp->buffer, sp->size * sizeof (char));
  641.     }
  642.   bcopy (name, sp->buffer + sp->used, len);
  643.   sp->used += len;
  644.   sp->n ++;
  645. }
  646.  
  647. void
  648. finish_sp (sp, v_count, v_vector)
  649.      register struct string_pool *sp;
  650.      int *v_count;
  651.      char ***v_vector;
  652. {
  653.   int i;
  654.   register char *p;
  655.   char **v;
  656.  
  657.   v = (char**) xmalloc ((sp->n + 1) * sizeof (char*));
  658.   *v++ = sp->buffer;
  659.   *v_vector = v;
  660.   *v_count = sp->n;
  661.   p = sp->buffer;
  662.   for (i = sp->n; i; i --)
  663.     {
  664.       *v++ = p;
  665.       if (i - 1)
  666.     p += strlen (p) + 1;
  667.     }
  668. }
  669.  
  670. void
  671. free_sp (vector)
  672.      char **vector;
  673. {
  674.   vector --;
  675.   free (*vector);        /* free string pool */
  676.   free (vector);
  677. }
  678.  
  679.  
  680. /*----------------------------------------------------------------------*/
  681. /*            READ DIRECTORY FILES                */
  682. /*----------------------------------------------------------------------*/
  683.  
  684. static boolean
  685. include_path_p (path, name)
  686.      char *path, *name;
  687. {
  688.   char *n = name;
  689.   while (*path)
  690.     if (*path++ != *n++)
  691.       return (path[-1] == '/' && *n == '\0');
  692.   return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/'));
  693. }
  694.  
  695. #define STREQU(a,b)    (((a)[0] == (b)[0]) ? (strcmp ((a),(b)) == 0) : FALSE)
  696. void
  697. cleaning_files (v_filec, v_filev)
  698.      int *v_filec;
  699.      char ***v_filev;
  700. {
  701.   char *flags;
  702.   struct stat stbuf;
  703.   register char **filev = *v_filev;
  704.   register int filec = *v_filec;
  705.   register char *p;
  706.   register int i, j;
  707.  
  708.   if (filec == 0)
  709.     return;
  710.  
  711.   flags = xmalloc (filec * sizeof (char));
  712.  
  713.   /* flags & 0x01 :    1: ignore */
  714.   /* flags & 0x02 :    1: directory, 0 : regular file */
  715.   /* flags & 0x04 :    1: need delete */
  716.  
  717.   for (i = 0; i < filec; i ++)
  718.     if (stat (filev[i], &stbuf) < 0)
  719.       {
  720.     flags[i] = 0x04;
  721.     fprintf (stderr,
  722.          "LHa: Cannot access \"%s\", ignored.\n", filev[i]);
  723.       }
  724.     else
  725.       {
  726.     if (is_regularfile (&stbuf))
  727.       flags[i] = 0x00;
  728.     else if (is_directory (&stbuf))
  729.       flags[i] = 0x02;
  730.     else
  731.       {
  732.         flags[i] = 0x04;
  733.         fprintf (stderr,
  734.              "LHa: Cannot archive \"%s\", ignored.\n", filev[i]);
  735.       }
  736.       }
  737.   errno = 0;
  738.  
  739.   for (i = 0; i < filec; i ++)
  740.     {
  741.       p = filev[i];
  742.       if ((flags[i] & 0x07) == 0x00)
  743.     {            /* regular file, not deleted/ignored */
  744.       for (j = i + 1; j < filec; j ++)
  745.         {
  746.           if ((flags[j] & 0x07) == 0x00)
  747.         {        /* regular file, not deleted/ignored */
  748.           if (STREQU (p, filev[j]))
  749.             flags[j] = 0x04; /* delete */
  750.         }
  751.         }
  752.     }
  753.       else if ((flags[i] & 0x07) == 0x02)
  754.     {            /* directory, not deleted/ignored */
  755.       for (j = i + 1; j < filec; j ++)
  756.         {
  757.           if ((flags[j] & 0x07) == 0x00)
  758.         {        /* regular file, not deleted/ignored */
  759.           if (include_path_p (p, filev[j]))
  760.             flags[j] = 0x04; /* delete */
  761.         }
  762.           else if ((flags[j] & 0x07) == 0x02)
  763.         {        /* directory, not deleted/ignored */
  764.           if (include_path_p (p, filev[j]))
  765.             flags[j] = 0x04; /* delete */
  766.         }
  767.         }
  768.     }
  769.     }
  770.  
  771.   for (i = j = 0; i < filec; i ++)
  772.     {
  773.       if ((flags[i] & 0x04) == 0)
  774.     {
  775.       if (i != j)
  776.         filev[j] = filev[i];
  777.       j ++;
  778.     }
  779.     }
  780.   *v_filec = j;
  781.  
  782.   free (flags);
  783. }
  784.  
  785. #ifdef NODIRECTORY
  786. /* please need your imprementation */
  787. boolean
  788. find_files (name, v_filec, v_filev)
  789.      char *name;
  790.      int *v_filec;
  791.      char ***v_filev;
  792. {
  793.   return FALSE;            /* DUMMY */
  794. }
  795.  
  796. void
  797. free_files (filec, filev)
  798.      int filec;
  799.      char **filev;
  800. {
  801.   /* do nothing */
  802. }
  803. #else
  804. boolean
  805. find_files (name, v_filec, v_filev)
  806.      char *name;
  807.      int *v_filec;
  808.      char ***v_filev;
  809. {
  810.   struct string_pool sp;
  811.   char newname[FILENAME_LENGTH];
  812.   int len, n;
  813.   DIR *dirp;
  814.   DIRENTRY *dp;
  815.   struct stat tmp_stbuf, arc_stbuf, fil_stbuf;
  816.  
  817.   strcpy (newname, name);
  818.   len = strlen (name);
  819.   if (len > 0 && newname[len-1] != '/')
  820.     newname[len++] = '/';
  821.  
  822.   dirp = opendir (name);
  823.   if (!dirp)
  824.     return FALSE;
  825.  
  826.   init_sp (&sp);
  827.  
  828.   GETSTAT(temporary_name, &tmp_stbuf);
  829.   GETSTAT(archive_name, &arc_stbuf);
  830.  
  831.   for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
  832.     {
  833.       n = NAMLEN (dp);
  834.       strncpy (newname+len, dp->d_name, n);
  835.       newname[len + n] = '\0';
  836.       if (GETSTAT(newname, &fil_stbuf) < 0) continue;
  837.       if ((dp->d_ino != 0) &&
  838.       /* exclude '.' and '..' */
  839.       ((dp->d_name[0] != '.') ||
  840.        ((n != 1) &&
  841.         ((dp->d_name[1] != '.') ||
  842.          (n != 2)))) &&
  843.       ((tmp_stbuf.st_dev != fil_stbuf.st_dev ||
  844.         tmp_stbuf.st_ino != fil_stbuf.st_ino) &&
  845.        (arc_stbuf.st_dev != fil_stbuf.st_dev ||
  846.         arc_stbuf.st_ino != fil_stbuf.st_ino)))
  847.  
  848.     {
  849.       add_sp (&sp, newname, len + n + 1);
  850.     }
  851.     }
  852.   closedir (dirp);
  853.   finish_sp (&sp, v_filec, v_filev);
  854.   if (*v_filec > 1)
  855.     qsort (*v_filev, *v_filec, sizeof (char*), sort_by_ascii);
  856.   cleaning_files (v_filec, v_filev);
  857.  
  858.   return TRUE;
  859. }
  860.  
  861. void
  862. free_files (filec, filev)
  863.      int filec;
  864.      char **filev;
  865. {
  866.   free_sp (filev);
  867. }
  868. #endif
  869.  
  870. /*----------------------------------------------------------------------*/
  871. /*                                    */
  872. /*----------------------------------------------------------------------*/
  873.  
  874. /* Build temporary file name and store to TEMPORARY_NAME */
  875. void
  876. build_temporary_name ()
  877. {
  878. #ifdef TMP_FILENAME_TEMPLATE
  879.   /* "/tmp/lhXXXXXX" etc. */
  880.   strcpy (temporary_name, TMP_FILENAME_TEMPLATE);
  881.   mktemp (temporary_name);
  882. #else
  883.   char *p, *s;
  884.  
  885.   strcpy (temporary_name, archive_name);
  886.   for (p = temporary_name, s = (char*)0; *p; p ++)
  887.     if (*p == '/')
  888.       s = p;
  889.   strcpy ((s ? s+1 : temporary_name), "lhXXXXXX");
  890.   mktemp (temporary_name);
  891. #endif
  892. }
  893.  
  894. static void
  895. modify_filename_extention (buffer, ext)
  896.      char *buffer;
  897.      char *ext;
  898. {
  899.   register char *p, *dot;
  900.  
  901.   for (p = buffer, dot = (char*)0; *p; p ++)
  902.     {
  903.       if (*p == '.')
  904.         dot = p;
  905.       else if (*p == '/')
  906.         dot = (char*)0;
  907.     }
  908.  
  909.   if (dot)
  910.     p = dot;
  911.  
  912.   strcpy (p, ext);
  913. }
  914.  
  915. /* build backup file name */
  916. void
  917. build_backup_name (buffer, original)
  918.      char *buffer;
  919.      char *original;
  920. {
  921.   strcpy (buffer, original);
  922.   modify_filename_extention (buffer, BACKUPNAME_EXTENTION); /* ".bak" */
  923. }
  924.  
  925. void
  926. build_standard_archive_name (buffer, orginal)
  927.      char *buffer;
  928.      char *orginal;
  929. {
  930.   strcpy (buffer, orginal);
  931.   modify_filename_extention (buffer, ARCHIVENAME_EXTENTION); /* ".lzh" */
  932. }
  933.  
  934. /*----------------------------------------------------------------------*/
  935. /*                                    */
  936. /*----------------------------------------------------------------------*/
  937.  
  938. extern int patmatch();
  939.  
  940. boolean
  941. need_file (name)
  942.      char *name;
  943. {
  944.   int i;
  945.  
  946.   if (cmd_filec == 0)
  947.     return TRUE;
  948.  
  949.   for (i = 0; i < cmd_filec; i ++)
  950.     {
  951.       if (patmatch(cmd_filev[i], name, 0 ) )
  952.         return TRUE;
  953.     }
  954.  
  955.   return FALSE;
  956. }
  957.  
  958. FILE *
  959. xfopen (name, mode)
  960.      char *name, *mode;
  961. {
  962.   FILE *fp;
  963.  
  964.   if ((fp = fopen (name, mode)) == NULL)
  965.     fatal_error (name);
  966.  
  967.   return fp;
  968. }
  969.  
  970.  
  971. /*----------------------------------------------------------------------*/
  972. /*                                    */
  973. /*----------------------------------------------------------------------*/
  974. int    archive_file_mode;
  975. int    archive_file_gid;
  976.  
  977. static boolean
  978. open_old_archive_1 (name, v_fp)
  979.      char *name;
  980.      FILE **v_fp;
  981. {
  982.   FILE *fp;
  983.   struct stat stbuf;
  984.  
  985.   if (stat (name, &stbuf) >= 0 &&
  986.       is_regularfile (&stbuf) &&
  987.       (fp = fopen (name, READ_BINARY)) != NULL)
  988.     {
  989.       *v_fp = fp;
  990.       archive_file_gid = stbuf.st_gid;
  991.       archive_file_mode = stbuf.st_mode;
  992.       return TRUE;
  993.     }
  994.  
  995.   *v_fp = NULL;
  996.   archive_file_gid = -1;
  997.   return FALSE;
  998. }
  999.  
  1000. FILE *
  1001. open_old_archive ()
  1002. {
  1003.   FILE *fp;
  1004.   char *p;
  1005.  
  1006.   if (!strcmp(archive_name, "-"))
  1007.     {
  1008.       if (cmd == CMD_EXTRACT || cmd == CMD_LIST) return stdin;
  1009.       else return NULL;
  1010.     }
  1011.   if (p = (char *)rindex(archive_name,'.'))
  1012.     {
  1013.       if ( strucmp(".LZH",p)==0
  1014.           || strucmp(".LZS",p)==0
  1015.           || strucmp(".COM",p)==0        /* DOS SFX */
  1016.           || strucmp(".EXE",p)==0
  1017.             || strucmp(".X"  ,p)==0        /* HUMAN SFX */
  1018.           || strucmp(".BAK",p)==0 )    /* for BackUp */
  1019.       {
  1020.         open_old_archive_1 (archive_name, &fp );
  1021.         return fp;
  1022.       }
  1023.     }
  1024.  
  1025.   if ( open_old_archive_1 (archive_name, &fp) )
  1026.         return fp;
  1027.   sprintf( expanded_archive_name , "%s.lzh",archive_name);
  1028.  
  1029.   if ( open_old_archive_1 (expanded_archive_name, &fp) )
  1030.   {
  1031.     archive_name = expanded_archive_name;
  1032.     return fp;
  1033.   }
  1034.   sprintf( expanded_archive_name, "%s.lzs",archive_name);
  1035.   if ( open_old_archive_1 (expanded_archive_name, &fp ) )
  1036.   {
  1037.       archive_name = expanded_archive_name;
  1038.     return fp;
  1039.   }
  1040.   return NULL;
  1041. }
  1042.  
  1043. int
  1044. inquire (msg, name, selective)
  1045.      char *msg, *name, *selective;
  1046. {
  1047.   char buffer[1024];
  1048.   char *p;
  1049.  
  1050.   for (;;)
  1051.     {
  1052.       fprintf (stderr, "%s %s ", name, msg);
  1053.       fflush (stderr);
  1054.  
  1055.       fgets (buffer, 1024, stdin);
  1056.  
  1057.       for (p = selective; *p; p++)
  1058.     if (buffer[0] == *p)
  1059.       return p - selective;
  1060.     }
  1061.   /*NOTREACHED*/
  1062. }
  1063.  
  1064. void
  1065. write_archive_tail (nafp)
  1066.      FILE *nafp;
  1067. {
  1068.   putc (0x00, nafp);
  1069. }
  1070.  
  1071. void
  1072. copy_old_one (oafp, nafp, hdr)
  1073.      FILE *oafp, *nafp;
  1074.      LzHeader *hdr;
  1075. {
  1076.   if (noexec)
  1077.     {
  1078.       fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
  1079.     }
  1080.   else
  1081.     {
  1082.       reading_filename = archive_name;
  1083.       writting_filename = temporary_name;
  1084.       copyfile (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size,0);
  1085.     }
  1086. }
  1087.  
  1088. /**************************************
  1089.  Added  31/8/1994  by Enrico Demarin
  1090. ***************************************/
  1091.  
  1092.  
  1093. int expand_wildcards(char *path,char *arg)
  1094.     HDIR handle = HDIR_CREATE;
  1095.     FILEFINDBUF3 ffbuf;
  1096.     ULONG count = 1;
  1097.     ULONG len = CCHMAXPATH;
  1098.     char *filter;
  1099.     char *fullname;
  1100.     char **newptr;
  1101.     APIRET goon;
  1102.     
  1103.  
  1104.  
  1105.     if (!path) path="";
  1106.     
  1107.     filter=(char *)malloc(strlen(path)+strlen(arg)+4);
  1108.     if (!filter) return FALSE;
  1109.     
  1110.     
  1111.     strcpy(filter,path);
  1112.     strcat(filter,arg);
  1113.  
  1114.     
  1115.     goon = DosFindFirst(filter, &handle,
  1116.             file_mask, (void *) &ffbuf, sizeof(ffbuf), &count, FIL_STANDARD);
  1117.     
  1118.     
  1119.  
  1120.     while (goon==NO_ERROR)
  1121.     {
  1122.       fullname=(char *)malloc(strlen(path)+strlen(ffbuf.achName)+4);
  1123.      
  1124.      if (!fullname) { free(filter); return FALSE;  } 
  1125.     
  1126.      if (ffbuf.achName[0]!='.')
  1127.      { 
  1128.        if (ffbuf.attrFile & FILE_DIRECTORY)
  1129.         {
  1130.              if (recurse_subdirs)
  1131.              { 
  1132.              sprintf(fullname,"%s%s\\",path,ffbuf.achName);
  1133.              expand_wildcards(fullname,arg);
  1134.              }
  1135.         } 
  1136.         
  1137.         if ((!(ffbuf.attrFile & FILE_DIRECTORY))||(recurse_subdirs))
  1138.         {
  1139.          
  1140.          sprintf(fullname,"%s%s",path,ffbuf.achName);
  1141.          cmd_filec++;
  1142.          newptr=(char **)realloc((void *)cmd_filev,(sizeof(char *))*cmd_filec);
  1143.          cmd_filev=newptr;
  1144.          convert_slash(fullname);
  1145.           cmd_filev[cmd_filec-1]=fullname;
  1146.          fullname=NULL;         
  1147.  
  1148.          } else free(fullname);
  1149.       }     
  1150.         count = 1;
  1151.         goon = DosFindNext(handle, &ffbuf, sizeof(ffbuf), &count);
  1152.         
  1153.     }
  1154.    
  1155.    if (handle) DosFindClose(handle);
  1156.    if (filter) free(filter);
  1157.     
  1158.     
  1159.    switch (goon)
  1160.     { 
  1161.      case NO_ERROR:
  1162.      case ERROR_NO_MORE_FILES:
  1163.                  return TRUE;      
  1164.      default:
  1165.           fatal_error("LHA Error : filename not matched!");
  1166.      } 
  1167.  
  1168. }
  1169.  
  1170.  
  1171. void convert_slash(char *dest)
  1172.  while (*dest) 
  1173.  { 
  1174.   if (*dest=='\\') *dest='/';
  1175.   dest++;
  1176.   }
  1177. }   
  1178.