home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / ARCHIVERS / lha208src.lzh / LHA / SRC / lharc.c < prev    next >
Text File  |  1994-12-02  |  31KB  |  1,113 lines

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