home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / ppc / lha_ppc / src / lharc.c < prev    next >
C/C++ Source or Header  |  1997-12-04  |  20KB  |  854 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. /*  DOS-Version Original LHx V C2.01         (C) H.Yohizaki        */
  20. /*                                    */
  21. /*  V2.00  UNIX Lharc + DOS LHx -> OSK LHx    1990.11.01  Momozou    */
  22. /*  V2.01  Minor Modified            1990.11.24  Momozou    */
  23. /*                                    */
  24. /*  V0.02  LHx for UNIX                1991.11.18  M.Oki    */
  25. /*  V0.03  LHa for UNIX                1991.12.17  M.Oki    */
  26. /*  V0.04  LHa for UNIX    beta version        1992.01.20  M.Oki    */
  27. /*  V1.00  LHa for UNIX    Fixed            1992.03.19  M.Oki    */
  28. /*----------------------------------------------------------------------*/
  29.  
  30. #include "lharc.h"
  31.  
  32. /*----------------------------------------------------------------------*/
  33. /*                PROGRAM                 */
  34. /*----------------------------------------------------------------------*/
  35.  
  36.  
  37. #define CMD_UNKNOWN    0
  38. #define CMD_EXTRACT    1
  39. #define CMD_ADD        2
  40. #define CMD_LIST    3
  41. #define CMD_DELETE    4
  42.  
  43. static int    cmd = CMD_UNKNOWN;
  44. char    **cmd_filev;
  45. int    cmd_filec;
  46.  
  47. char    *archive_name;
  48. char    expanded_archive_name[FILENAME_LENGTH];
  49. char    temporary_name[FILENAME_LENGTH];
  50. char    backup_archive_name[FILENAME_LENGTH];
  51.  
  52. /* static functions */
  53. static void sort_files(void);
  54.  
  55. /* options */
  56. boolean    quiet = FALSE;
  57. boolean    text_mode = FALSE;
  58. boolean    verbose = FALSE;
  59. boolean    noexec = FALSE;    /* debugging option */
  60. boolean    force = FALSE;
  61. boolean    prof = FALSE;
  62. int compress_method = 5;    /* deafult -lh5- */
  63. int header_level = HEADER_LEVEL1;
  64. #ifdef EUC
  65. boolean euc_mode = FALSE;
  66. #endif
  67.  
  68. /* view command flags */
  69. boolean    verbose_listing = FALSE;
  70.  
  71. /* extract command flags */
  72. boolean    output_to_stdout = FALSE;
  73.  
  74. /* append command flags */
  75. boolean    new_archive = FALSE;
  76. boolean    update_if_newer = FALSE;
  77. boolean    delete_after_append = FALSE;
  78. boolean    generic_format = FALSE;
  79.  
  80. boolean    remove_temporary_at_error = FALSE;
  81. boolean    recover_archive_when_interrupt = FALSE;
  82. boolean    remove_extracting_file_when_interrupt = FALSE;
  83. boolean get_filename_from_stdin = FALSE;
  84. boolean ignore_directory = FALSE;
  85. boolean verify_mode = FALSE;
  86.  
  87. char *extract_directory = NULL;
  88. char **xfilev;
  89. int  xfilec = 257;
  90.  
  91. /*----------------------------------------------------------------------*/
  92. /* NOTES :        Text File Format                */
  93. /*    GENERATOR        NewLine                    */
  94. /*    [generic]        0D 0A                    */
  95. /*    [MS-DOS]        0D 0A                    */
  96. /*    [OS9][MacOS]        0D                    */
  97. /*    [UNIX]            0A                    */
  98. /*----------------------------------------------------------------------*/
  99.  
  100.  
  101. static void print_tiny_usage_and_exit(void)
  102. {
  103.     fprintf (stderr,
  104. "LHarc    for UNIX  V 1.02  Copyright(C) 1989  Y.Tagawa\n"
  105. "LHx      for MSDOS V C2.01 Copyright(C) 1990  H.Yoshizaki\n"
  106. "LHx(arc) for OSK   V 2.01  Modified     1990  Momozou\n"
  107. "LHa      for UNIX  V 1.00  Copyright(C) 1992  Masaru Oki\n");
  108.  
  109.     fprintf(stderr,
  110. "usage: lha [-]{axelvudmcp}[qvnfodizg012][w=<dir>] archive_file [file...]\n"
  111. "commands:                           options:\n"
  112. " a   Add(or replace) to archive      q  quiet\n"
  113. " x,e EXtract from archive            v  verbose\n"
  114. " l,v List / Verbose List             n  not execute\n"
  115. " u   Update newer files to archive   f  force (over write at extract)\n"
  116. " d   Delete from archive             t  FILES are TEXT file\n"
  117. " m   Move to archive (means 'ad')    o  use LHarc compatible method (a/u)\n"
  118. " c   re-Construct new archive        w=<dir> specify extract directory (x/e)\n"
  119. " p   Print to STDOUT from archive    d  delete FILES after (a/u/c)\n"
  120. " t   Test file CRC in archive        i  ignore directory path (x/e)\n"
  121. "                                     z  files not compress (a/u)\n"
  122. "                                     g  [Generic] format (for compatibility)\n"
  123. "                                     0/1/2 header level (a/u)\n");
  124. #ifdef EUC
  125.     fprintf (stderr,
  126. "                                     e  TEXT code convert from/to EUC\n");
  127. #endif
  128.     exit (1);
  129. }
  130.  
  131. /* TEMPORARY */
  132. long __bufsiz = 4096;
  133.  
  134. void main(int argc, char *argv[])
  135. {
  136.     char *p, inpbuf[256];
  137.  
  138.     if (argc < 2)
  139.     print_tiny_usage_and_exit();
  140.     if (argc < 3)
  141.     {
  142.     cmd = CMD_LIST;
  143.     argv--;
  144.     argc++;
  145.     goto work;
  146.     }
  147.     if (argv[1][0]=='-')
  148.     argv[1]++;
  149.  
  150.     /* commands */
  151.     switch (argv[1][0])
  152.     {
  153.     case 'x':
  154.     case 'e':
  155.         cmd = CMD_EXTRACT;
  156.         break;
  157.  
  158.     case 'p':
  159.         output_to_stdout = TRUE;
  160.         cmd = CMD_EXTRACT;
  161.         break;
  162.  
  163.     case 'c':
  164.         new_archive = TRUE;
  165.         cmd = CMD_ADD;
  166.         break;
  167.  
  168.     case 'a':
  169.         cmd = CMD_ADD;
  170.         break;
  171.  
  172.     case 'd':
  173.         cmd = CMD_DELETE;
  174.         break;
  175.  
  176.     case 'u':
  177.         update_if_newer = TRUE;
  178.         cmd = CMD_ADD;
  179.         break;
  180.  
  181.     case 'm':
  182.         delete_after_append = TRUE;
  183.         cmd = CMD_ADD;
  184.         break;
  185.  
  186.     case 'v':
  187.         verbose_listing = TRUE;
  188.         cmd = CMD_LIST;
  189.         break;
  190.  
  191.     case 'l':
  192.         cmd = CMD_LIST;
  193.         break;
  194.  
  195.     case 't':
  196.         cmd = CMD_EXTRACT;
  197.         verify_mode = TRUE;
  198.         break;
  199.  
  200.     default:
  201.         print_tiny_usage_and_exit();
  202.     }
  203.  
  204.     /* options */
  205.     p = &argv[1][1];
  206.     for (p = &argv[1][1]; *p; )
  207.     {
  208.     switch ((*p++))
  209.     {
  210.         case 'q':    quiet = TRUE; break;
  211.         case 'f':    force = TRUE; break;
  212.         case 'p':    prof = TRUE; break;
  213.         case 'v':    verbose = TRUE; break;
  214.         case 't':    text_mode = TRUE; break;
  215. #ifdef EUC
  216.         case 'e':    text_mode = TRUE; euc_mode = TRUE; break;
  217. #endif
  218.         case 'n':    noexec = TRUE; break;
  219.         case 'g':    generic_format = TRUE; header_level = 0; break;
  220.         case 'd':    delete_after_append = TRUE; break;
  221.         case 'o':    compress_method = 1; header_level = 0; break;
  222.         case 'z':    compress_method = 0; break;
  223.         case 'i':    ignore_directory = TRUE; break;
  224.         case 'w':    if (*p=='=') p++;
  225.             extract_directory=p;
  226.                 while (*p) p++;
  227.                     break;
  228.         case '0':    header_level = HEADER_LEVEL0; break;
  229.         case '1':    header_level = HEADER_LEVEL1; break;
  230.         case '2':    header_level = HEADER_LEVEL2; break;
  231.         default:
  232.         {
  233.         fprintf(stderr, "LHa: Unknown option '%c'.\n", p[-1]);
  234.         exit(1);
  235.         }
  236.     }
  237.     }
  238.  
  239. work:
  240.     /* archive file name */
  241.     archive_name = argv[2];
  242.  
  243.     if (!strcmp(archive_name, "-"))
  244.     {
  245.     if (!isatty(1) && cmd == CMD_ADD) quiet = TRUE;
  246.     }
  247.     else
  248.     {
  249.     if (argc == 3 && !isatty(0))
  250.         get_filename_from_stdin = TRUE;
  251.     }
  252.  
  253.     /* target file name */
  254.     if (get_filename_from_stdin)
  255.     {
  256.     cmd_filec = 0;
  257.     if ((xfilev = (char **)malloc(sizeof(char *) * xfilec)) == NULL)
  258.         fatal_error("Virtual memory exhausted\n");
  259.     while (gets(inpbuf))
  260.     {
  261.         if (cmd_filec >= xfilec)
  262.         {
  263.         xfilec += 256;
  264.         cmd_filev = (char **)realloc(xfilev, sizeof(char *) * xfilec);
  265.         if (cmd_filev == NULL)
  266.             fatal_error("Virtual memory exhausted\n");
  267.         xfilev = cmd_filev;
  268.         }                
  269.         if (strlen(inpbuf) < 1) continue;
  270.         if ((xfilev[cmd_filec++]=(char *)strdup(inpbuf))==NULL)
  271.         fatal_error("Virtual memory exhausted\n");
  272.      }
  273.      xfilev[cmd_filec] = NULL;
  274.      cmd_filev = xfilev;
  275.     }
  276.     else
  277.     {
  278.     cmd_filec = argc - 3;
  279.     cmd_filev = argv + 3;
  280.     }
  281.     sort_files ();
  282.  
  283.     /* make crc table */
  284.     make_crctable();
  285.  
  286.     switch (cmd)
  287.     {
  288.     case CMD_EXTRACT:    cmd_extract();    break;
  289.     case CMD_ADD:        cmd_add();    break;
  290.     case CMD_LIST:        cmd_list();    break;
  291.     case CMD_DELETE:    cmd_delete();    break;
  292.     }
  293.  
  294. #ifdef USE_PROF
  295.     if (!prof)
  296.     exit(0);
  297. #endif
  298.  
  299.     exit(0);
  300. }
  301.  
  302. static void message_1(char *title, char *subject, char *name)
  303. {
  304.     fprintf(stderr, "LHa: %s%s ", title, subject);
  305.     fflush(stderr);
  306.  
  307.     if (errno == 0)
  308.     fprintf(stderr, "%s\n", name);
  309.     else
  310.     perror(name);
  311. }
  312.  
  313. void message(char *subject, char *name)
  314. {
  315.     message_1("", subject, name);
  316. }
  317.  
  318. void warning(char *subject, char *name)
  319. {
  320.     message_1("Warning: ", subject, name);
  321. }
  322.  
  323. void error(char *subject, char *msg)
  324. {
  325.     message_1("Error: ", subject, msg);
  326. }
  327.  
  328. void fatal_error(char *msg)
  329. {
  330.     message_1("Fatal error:", "", msg);
  331.  
  332.     if (remove_temporary_at_error)
  333.     unlink(temporary_name);
  334.  
  335.     exit(1);
  336. }
  337.  
  338. char *writting_filename;
  339. char *reading_filename;
  340.  
  341. void write_error(void)
  342. {
  343.     fatal_error (writting_filename);
  344. }
  345.  
  346. void read_error(void)
  347. {
  348.     fatal_error (reading_filename);
  349. }
  350.  
  351. void interrupt(int signo)
  352. {
  353.     errno = 0;
  354.     message ("Interrupted\n", "");
  355.  
  356.     if (temporary_fp)
  357.     fclose(temporary_fp);
  358.     unlink(temporary_name);
  359.     if (recover_archive_when_interrupt)
  360.     rename(backup_archive_name, archive_name);
  361.     if (remove_extracting_file_when_interrupt)
  362.     {
  363.     errno = 0;
  364.     message("Removing", writting_filename);
  365.     unlink(writting_filename);
  366.     }
  367.     signal (SIGINT, SIG_DFL);
  368. #ifndef AMIGA
  369.     signal (SIGHUP, SIG_DFL);
  370.     kill (getpid (), signo);
  371. #endif
  372. }
  373.  
  374.  
  375.  
  376. /*----------------------------------------------------------------------*/
  377. /*                                    */
  378. /*----------------------------------------------------------------------*/
  379.  
  380. static int sort_by_ascii(char **a, char **b)
  381. {
  382.     char *p, *q;
  383.     int c1, c2;
  384.  
  385.     p = *a, q = *b;
  386.     if (generic_format)
  387.     {
  388.     do
  389.     {
  390.         c1 = *(unsigned char*)p ++;
  391.         c2 = *(unsigned char*)q ++;
  392.         if (!c1 || !c2)
  393.         break;
  394.         if (islower(c1))
  395.         c1 = toupper(c1);
  396.         if (islower(c2))
  397.         c2 = toupper(c2);
  398.     }
  399.         while (c1 == c2);
  400.         return c1 - c2;
  401.     }
  402.     else
  403.     {
  404.     while (*p == *q && *p != '\0')
  405.         p ++, q ++;
  406.     return *(unsigned char*)p - *(unsigned char*)q;
  407.     }
  408. }
  409.  
  410. static void sort_files(void)
  411. {
  412.     if (cmd_filec > 1)
  413.     qsort(cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
  414. }
  415.  
  416. char *xmalloc(int size)
  417. {
  418.     char *p = (char *)malloc (size);
  419.  
  420.     if (!p)
  421.     fatal_error("Not enough memory");
  422.     return p;
  423. }
  424.  
  425. char *xrealloc(char *old, int size)
  426. {
  427.     char *p = (char *)realloc(old, size);
  428.  
  429.     if (!p)
  430.     fatal_error("Not enough memory");
  431.     return p;
  432. }
  433.  
  434. /*----------------------------------------------------------------------*/
  435. /*                STRING POOL                */
  436. /*----------------------------------------------------------------------*/
  437.  
  438. /*
  439.  * string pool :
  440.  *    +-------------+-------------+---     ---+-------------+----------+
  441.  *    | N A M E 1 \0| N A M E 2 \0|    ...    | N A M E n \0|             |
  442.  *    +-------------+-------------+---     ---+-------------+----------+
  443.  *    ^                              ^         ^
  444.  * buffer+0                        buffer+used  buffer+size
  445.  */
  446.  
  447. /*
  448.  * vector :
  449.  *    +---------------+---------------+-------------     -------------+
  450.  *    | pointer to    | pointer to    | pointer to   ...  pointer to    |
  451.  *    |  string pool    |  N A M E 1    |  N A M E 2   ...   N A M E n    |
  452.  *    +---------------+---------------+-------------     -------------+
  453.  *    ^        ^
  454.  *   malloc base      returned
  455.  */
  456.  
  457. void init_sp(struct string_pool *sp)
  458. {
  459.     sp->size = 1024 - 8;        /* any ( >=0 ) */
  460.     sp->used = 0;
  461.     sp->n = 0;
  462.     sp->buffer = (char*)xmalloc (sp->size * sizeof (char));
  463. }
  464.  
  465. void add_sp(struct string_pool *sp, char *name, int len)
  466. {
  467.     while (sp->used + len > sp->size)
  468.     {
  469.     sp->size *= 2;
  470.     sp->buffer = (char*)xrealloc(sp->buffer, sp->size * sizeof (char));
  471.     }
  472.     bcopy (name, sp->buffer + sp->used, len);
  473.     sp->used += len;
  474.     sp->n ++;
  475. }
  476.  
  477. void finish_sp(struct string_pool *sp, int *v_count, char ***v_vector)
  478. {
  479.     int i;
  480.     char *p;
  481.     char **v;
  482.  
  483.     v = (char**) xmalloc ((sp->n + 1) * sizeof (char*));
  484.     *v++ = sp->buffer;
  485.     *v_vector = v;
  486.     *v_count = sp->n;
  487.     p = sp->buffer;
  488.     for (i = sp->n; i; i --)
  489.     {
  490.     *v++ = p;
  491.     if (i - 1)
  492.         p += strlen (p) + 1;
  493.     }
  494. }
  495.  
  496. void free_sp(char **vector)
  497. {
  498.     vector--;
  499.     free(*vector);        /* free string pool */
  500.     free(vector);
  501. }
  502.  
  503. /*----------------------------------------------------------------------*/
  504. /*            READ DIRECTORY FILES                */
  505. /*----------------------------------------------------------------------*/
  506.  
  507. static boolean include_path_p(char *path, char *name)
  508. {
  509.     char *n = name;
  510.  
  511.     while (*path)
  512.     if (*path++ != *n++)
  513.         return (path[-1] == '/' && *n == '\0');
  514.     return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/'));
  515. }
  516.  
  517. #define STREQU(a,b) (((a)[0] == (b)[0]) ? (strcmp ((a),(b)) == 0) : FALSE)
  518.  
  519. void cleaning_files(int *v_filec, char ***v_filev)
  520. {
  521.     char *flags;
  522.     struct stat stbuf;
  523.     char **filev = *v_filev;
  524.     int filec = *v_filec;
  525.     char *p;
  526.     int i, j;
  527.  
  528.     if (filec == 0)
  529.     return;
  530.  
  531.     flags = xmalloc (filec * sizeof (char));
  532.  
  533.     /* flags & 0x01 :    1: ignore */
  534.     /* flags & 0x02 :    1: directory, 0 : regular file */
  535.     /* flags & 0x04 :    1: need delete */
  536.  
  537.     for (i = 0; i < filec; i ++)
  538.     {
  539.     if (stat (filev[i], &stbuf) < 0)
  540.     {
  541.         flags[i] = 0x04;
  542.         fprintf (stderr, "LHa: Cannot access \"%s\", ignored.\n", filev[i]);
  543.     }
  544.     else
  545.     {
  546.         if (is_regularfile (&stbuf))
  547.         flags[i] = 0x00;
  548.         else if (is_directory (&stbuf))
  549.         flags[i] = 0x02;
  550.         else
  551.         {
  552.         flags[i] = 0x04;
  553.         fprintf (stderr, "LHa: Cannot archive \"%s\", ignored.\n", filev[i]);
  554.         }
  555.     }
  556.     }
  557.     errno = 0;
  558.  
  559.     for (i = 0; i < filec; i ++)
  560.     {
  561.     p = filev[i];
  562.     if ((flags[i] & 0x07) == 0x00)
  563.     {            /* regular file, not deleted/ignored */
  564.         for (j = i + 1; j < filec; j ++)
  565.         {
  566.         if ((flags[j] & 0x07) == 0x00)
  567.         {        /* regular file, not deleted/ignored */
  568.             if (STREQU (p, filev[j]))
  569.             flags[j] = 0x04; /* delete */
  570.         }
  571.         }
  572.     }
  573.         else if ((flags[i] & 0x07) == 0x02)
  574.     {            /* directory, not deleted/ignored */
  575.         for (j = i + 1; j < filec; j ++)
  576.         {
  577.         if ((flags[j] & 0x07) == 0x00)
  578.         {        /* regular file, not deleted/ignored */
  579.             if (include_path_p (p, filev[j]))
  580.             flags[j] = 0x04; /* delete */
  581.         }
  582.         else if ((flags[j] & 0x07) == 0x02)
  583.         {        /* directory, not deleted/ignored */
  584.             if (include_path_p (p, filev[j]))
  585.             flags[j] = 0x04; /* delete */
  586.         }
  587.         }
  588.     }
  589.     }
  590.  
  591.     for (i = j = 0; i < filec; i ++)
  592.     {
  593.     if ((flags[i] & 0x04) == 0)
  594.     {
  595.         if (i != j)
  596.         filev[j] = filev[i];
  597.         j ++;
  598.     }
  599.     }
  600.     *v_filec = j;
  601.  
  602.     free (flags);
  603. }
  604.  
  605. boolean find_files(char *name, int *v_filec, char ***v_filev)
  606. {
  607.     struct string_pool sp;
  608.     char newname[FILENAME_LENGTH];
  609.     int len, n;
  610.     DIR *dirp;
  611.     DIRENTRY *dp;
  612.     struct stat tmp_stbuf, arc_stbuf, fil_stbuf;
  613.  
  614.     strcpy (newname, name);
  615.     len = strlen (name);
  616.     if (len > 0 && newname[len-1] != '/')
  617.     newname[len++] = '/';
  618.  
  619.     dirp = opendir (name);
  620.     if (!dirp)
  621.     return FALSE;
  622.  
  623.     init_sp (&sp);
  624.  
  625.     GETSTAT(temporary_name, &tmp_stbuf);
  626.     GETSTAT(archive_name, &arc_stbuf);
  627.  
  628.     for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
  629.     {
  630.     n = NAMLEN (dp);
  631.     strncpy (newname+len, dp->d_name, n);
  632.     newname[len + n] = '\0';
  633.     if (GETSTAT(newname, &fil_stbuf) < 0) continue;
  634.     if ((dp->d_ino != 0) &&
  635.         /* exclude '.' and '..' */
  636.         ((dp->d_name[0] != '.') ||
  637.          ((n != 1) &&
  638.          ((dp->d_name[1] != '.') ||
  639.           (n != 2)))) &&
  640.         ((tmp_stbuf.st_dev != fil_stbuf.st_dev ||
  641.          tmp_stbuf.st_ino != fil_stbuf.st_ino) &&
  642.         (arc_stbuf.st_dev != fil_stbuf.st_dev ||
  643.          arc_stbuf.st_ino != fil_stbuf.st_ino)))
  644.     {
  645.         add_sp (&sp, newname, len + n + 1);
  646.     }
  647.     }
  648.     closedir (dirp);
  649.     finish_sp (&sp, v_filec, v_filev);
  650.     if (*v_filec > 1)
  651.     qsort (*v_filev, *v_filec, sizeof (char*), sort_by_ascii);
  652.     cleaning_files (v_filec, v_filev);
  653.  
  654.     return TRUE;
  655. }
  656.  
  657. void free_files(int filec, char **filev)
  658. {
  659.     free_sp (filev);
  660. }
  661.  
  662. /*----------------------------------------------------------------------*/
  663. /*                                    */
  664. /*----------------------------------------------------------------------*/
  665.  
  666. /* Build temporary file name and store to TEMPORARY_NAME */
  667. void build_temporary_name(void)
  668. {
  669.     char *p, *s;
  670.  
  671.     strcpy(temporary_name, archive_name);
  672.     for (p = temporary_name, s = NULL; *p; p ++)
  673.     if (*p == '/')
  674.         s = p;
  675.     strcpy((s ? s+1 : temporary_name), "lhXXXXXX");
  676.     mktemp(temporary_name);
  677. }
  678.  
  679. static void modify_filename_extention(char *buffer, char *ext)
  680. {
  681.     char *p, *dot;
  682.  
  683.     for (p = buffer, dot = (char*)0; *p; p ++)
  684.     {
  685.     if (*p == '.')
  686.         dot = p;
  687.     else if (*p == '/')
  688.         dot = NULL;
  689.     }
  690.  
  691.     if (dot)
  692.     p = dot;
  693.  
  694.     strcpy(p, ext);
  695. }
  696.  
  697. /* build backup file name */
  698. void build_backup_name(char *buffer, char *original)
  699. {
  700.     strcpy(buffer, original);
  701.     modify_filename_extention(buffer, BACKUPNAME_EXTENTION); /* ".bak" */
  702. }
  703.  
  704. void build_standard_archive_name(char *buffer, char *orginal)
  705. {
  706.     strcpy(buffer, orginal);
  707.     modify_filename_extention(buffer, ARCHIVENAME_EXTENTION); /* ".lzh" */
  708. }
  709.  
  710. /*----------------------------------------------------------------------*/
  711. /*                                    */
  712. /*----------------------------------------------------------------------*/
  713.  
  714. boolean need_file(char *name)
  715. {
  716.     int i;
  717.  
  718.     if (cmd_filec == 0)
  719.     return TRUE;
  720.  
  721.     for (i = 0; i < cmd_filec; i ++)
  722.     {
  723.     if (patmatch(cmd_filev[i], name, 0 ) )
  724.         return TRUE;
  725.     }
  726.  
  727.     return FALSE;
  728. }
  729.  
  730. FILE *xfopen(char *name, char *mode)
  731. {
  732.     FILE *fp;
  733.  
  734.     if ((fp = fopen (name, mode)) == NULL)
  735.     fatal_error (name);
  736.  
  737.     return fp;
  738. }
  739.  
  740. /*----------------------------------------------------------------------*/
  741. /*                                    */
  742. /*----------------------------------------------------------------------*/
  743. int archive_file_mode;
  744. int archive_file_gid;
  745.  
  746. static boolean open_old_archive_1(char *name, FILE **v_fp)
  747. {
  748.     FILE *fp;
  749.     struct stat stbuf;
  750.  
  751.     if (stat (name, &stbuf) >= 0 &&
  752.         is_regularfile (&stbuf) &&
  753.         (fp = fopen (name, READ_BINARY)) != NULL)
  754.     {
  755.     *v_fp = fp;
  756.     archive_file_gid = stbuf.st_gid;
  757.     archive_file_mode = stbuf.st_mode;
  758.     return TRUE;
  759.     }
  760.  
  761.     *v_fp = NULL;
  762.     archive_file_gid = -1;
  763.     return FALSE;
  764. }
  765.  
  766. FILE *open_old_archive(void)
  767. {
  768.     FILE *fp;
  769.     char *p;
  770.  
  771.     if (!strcmp(archive_name, "-"))
  772.     {
  773.     if (cmd == CMD_EXTRACT || cmd == CMD_LIST) return stdin;
  774.     else return NULL;
  775.     }
  776.     if (p = (char *)rindex(archive_name,'.'))
  777.     {
  778.     if (stricmp(".LHA",p)==0 ||
  779.         stricmp(".LZH",p)==0 ||
  780.         stricmp(".LZS",p)==0 ||
  781.         stricmp(".COM",p)==0 ||        /* DOS SFX */
  782.         stricmp(".EXE",p)==0 ||
  783.         stricmp(".X"  ,p)==0 ||        /* HUMAN SFX */
  784.         stricmp(".BAK",p)==0 )        /* for BackUp */
  785.     {
  786.         open_old_archive_1(archive_name, &fp);
  787.         return fp;
  788.     }
  789.     }
  790.  
  791.     if (open_old_archive_1(archive_name, &fp))
  792.         return fp;
  793.  
  794.     sprintf(expanded_archive_name , "%s.lha",archive_name);
  795.     if (open_old_archive_1(expanded_archive_name, &fp))
  796.     {
  797.     archive_name = expanded_archive_name;
  798.     return fp;
  799.     }
  800.  
  801.     sprintf( expanded_archive_name , "%s.lzh",archive_name);
  802.     if ( open_old_archive_1 (expanded_archive_name, &fp) )
  803.     {
  804.     archive_name = expanded_archive_name;
  805.     return fp;
  806.     }
  807.  
  808.     sprintf( expanded_archive_name, "%s.lzs",archive_name);
  809.     if ( open_old_archive_1 (expanded_archive_name, &fp ) )
  810.     {
  811.       archive_name = expanded_archive_name;
  812.     return fp;
  813.     }
  814.     return NULL;
  815. }
  816.  
  817. int inquire(char *msg, char *name, char *selective)
  818. {
  819.     char buffer[1024];
  820.     char *p;
  821.  
  822.     for (;;)
  823.     {
  824.     fprintf (stderr, "%s %s ", name, msg);
  825.     fflush (stderr);
  826.  
  827.     fgets (buffer, 1024, stdin);
  828.  
  829.     for (p = selective; *p; p++)
  830.         if (buffer[0] == *p)
  831.         return p - selective;
  832.     }
  833.   /*NOTREACHED*/
  834. }
  835.  
  836. void write_archive_tail(FILE *nafp)
  837. {
  838.     putc (0x00, nafp);
  839. }
  840.  
  841. void copy_old_one(FILE *oafp, FILE *nafp, LzHeader *hdr)
  842. {
  843.     if (noexec)
  844.     {
  845.     fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
  846.     }
  847.     else
  848.     {
  849.     reading_filename = archive_name;
  850.     writting_filename = temporary_name;
  851.     copyfile (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size,0);
  852.     }
  853. }
  854.