/*----------------------------------------------------------------------*/
/*              LHarc Archiver Driver for UNIX                          */
/*                                                                      */
/*              Copyright(C) MCMLXXXIX  Yooichi.Tagawa                  */
/*                                                                      */
/*  V1.00  Fixed                                1989.09.22  Y.Tagawa    */
/*----------------------------------------------------------------------*/


#include <ctype.h>
#include <signal.h>

#include <exec/types.h>
#include <time.h>
#include <fcntl.h>
#include <stat.h>

#include <string.h>

#define WRITE_BINARY    "w"
#define READ_BINARY     "r"

/*----------------------------------------------------------------------*/
/*                      MEMORY FUNCTIONS                                */
/*----------------------------------------------------------------------*/

#ifdef __ANSI__
#include "mem.h"
#define bcmp(a,b,n) memcmp ((a),(b),(n))
#define bcopy(s,d,n) memmove((d),(s),(n))
#define bzero(d,n) memset((d),0,(n))
#else   /* not __ANSI__ */
#include <exec/memory.h>
#define bcmp(a,b,n) memcmp ((a),(b),(n))
#define bcopy(s,d,n) memcpy ((d),(s),(n))       /* movmem((s),(d),(n)) */
#define bzero(d,n) memset((d),0,(n))
#endif  /* not __ANSI__ */


/*----------------------------------------------------------------------*/
/*                      YOUR CUSTOMIZATIONS                             */
/*----------------------------------------------------------------------*/
/* These definitions are changable to you likings. */
/* #define ARCHIVENAME_EXTENTION        ".LZH"          */
/* #define BACKUPNAME_EXTENTION         ".BAK"          */
/* #define TMP_FILENAME_TEMPLATE        "/usr/tmp/lhXXXXXX" */
/* #define MULTIBYTE_CHAR                               */
/* #define USE_PROF                                     */


#ifndef ARCHIVENAME_EXTENTION
#       define ARCHIVENAME_EXTENTION    ".lzh"
#endif
#ifndef BACKUPNAME_EXTENTION
#       define BACKUPNAME_EXTENTION     ".bak"
#endif
#ifndef TMP_FILENAME_TEMPLATE
#       define TMP_FILENAME_TEMPLATE    "/tmp/lhXXXXXX"
#endif

#define SJC_FIRST_P(c)                  \
  (((unsigned char)(c) >= 0x80) &&      \
   (((unsigned char)(c) < 0xa0) ||      \
    ((unsigned char)(c) >= 0xe0) &&     \
    ((unsigned char)(c) < 0xfd)))
#define SJC_SECOND_P(c)                 \
  (((unsigned char)(c) >= 0x40) &&      \
   ((unsigned char)(c) < 0xfd) &&       \
   ((ungigned char)(c) != 0x7f))

#ifdef MULTIBYTE_CHAR
#       define MULTIBYTE_FIRST_P        SJC_FIRST_P
#       define MULTIBYTE_SECOND_P       SJC_SECOND_P
#endif

/*----------------------------------------------------------------------*/
/*                      OTHER DIFINITIONS                               */
/*----------------------------------------------------------------------*/

/* Your C-Compiler has no 'void' */
#ifdef NO_VOID
#       define void
#endif

#ifndef SEEK_SET
#       define SEEK_SET 0
#       define SEEK_CUR 1
#       define SEEK_END 2
#endif

#       define FILENAME_LENGTH  255

#include <stdio.h>

/* non-integral functions */
extern struct tm *localtime ();
extern char *getenv ();
extern char *malloc ();
extern char *realloc ();


/* external variables */
extern int errno;


#define FALSE   0
#define TRUE    1
typedef int boolean;


/*----------------------------------------------------------------------*/
/*              LHarc FILE DIFINITIONS                                  */
/*----------------------------------------------------------------------*/
#define METHOD_TYPE_STRAGE      5
#define LZHUFF0_METHOD          "-lh0-"
#define LZHUFF1_METHOD          "-lh1-"
#define LZHUFF5_METHOD          "-lh5-"
#define LARC4_METHOD            "-lz4-"
#define LARC5_METHOD            "-lz5-"

#define I_HEADER_SIZE                   0
#define I_HEADER_CHECKSUM               1
#define I_METHOD                        2
#define I_PACKED_SIZE                   7
#define I_ORIGINAL_SIZE                 11
#define I_LAST_MODIFIED_STAMP           15
#define I_ATTRIBUTE                     19
#define I_NAME_LENGTH                   21
#define I_NAME                          22

#define I_CRC                           22 /* + name_length */
#define I_EXTEND_TYPE                   24 /* + name_length */
#define I_MINOR_VERSION                 25 /* + name_length */
#define I_UNIX_LAST_MODIFIED_STAMP      26 /* + name_length */
#define I_UNIX_MODE                     30 /* + name_length */
#define I_UNIX_UID                      32 /* + name_length */
#define I_UNIX_GID                      34 /* + name_length */
#define I_UNIX_EXTEND_BOTTOM            36 /* + name_length */

#define I_GENERIC_HEADER_BOTTOM         I_EXTEND_TYPE



#define EXTEND_GENERIC  0
#define EXTEND_UNIX     'U'
#define EXTEND_MSDOS    'M'
#define EXTEND_MACOS    'm'
#define EXTEND_OS9      '9'
#define EXTEND_OS2      '2'
#define EXTEND_OS68K    'K'
#define EXTEND_OS386    '3'
#define EXTEND_HUMAN    'H'
#define EXTEND_CPM      'C'
#define EXTEND_FLEX     'F'

#define GENERIC_ATTRIBUTE               0x20
#define GENERIC_DIRECTORY_ATTRIBUTE     0x10

#define CURRENT_UNIX_MINOR_VERSION      0x00



typedef struct LzHeader {
  unsigned char         header_size;
  char                  method[METHOD_TYPE_STRAGE];
  long                  packed_size;
  long                  original_size;
  long                  last_modified_stamp;
  unsigned short        attribute;
  char                  name[256];
  unsigned short        crc;
  boolean               has_crc;
  unsigned char         extend_type;
  unsigned char         minor_version;
  /*  extend_type == EXTEND_UNIX  and convert from other type. */
  time_t                unix_last_modified_stamp;
  unsigned short        unix_mode;
  unsigned short        unix_uid;
  unsigned short        unix_gid;
} LzHeader;

#define UNIX_FILE_TYPEMASK      0170000
#define UNIX_FILE_REGULAR       0100000
#define UNIX_FILE_DIRECTORY     0040000
#define UNIX_SETUID             0004000
#define UNIX_SETGID             0002000
#define UNIX_STYCKYBIT          0001000
#define UNIX_OWNER_READ_PERM    0000400
#define UNIX_OWNER_WRITE_PERM   0000200
#define UNIX_OWNER_EXEC_PERM    0000100
#define UNIX_GROUP_READ_PERM    0000040
#define UNIX_GROUP_WRITE_PERM   0000020
#define UNIX_GROUP_EXEC_PERM    0000010
#define UNIX_OTHER_READ_PERM    0000004
#define UNIX_OTHER_WRITE_PERM   0000002
#define UNIX_OTHER_EXEC_PERM    0000001
#define UNIX_RW_RW_RW           0000666

#define LZHEADER_STRAGE         256

/* used by qsort() for alphabetic-sort */
#define STRING_COMPARE(a,b) strcmp((a),(b))

struct string_pool {
  int used;
  int size;
  int n;
  char *buffer;
};


/*----------------------------------------------------------------------*/
/*                      OPTIONS                                         */
/*----------------------------------------------------------------------*/

/* command line options (common options) */
extern boolean  quiet;
extern boolean  text_mode;
extern boolean  verbose;
extern boolean  noexec;         /* debugging option */
extern boolean  force;
extern boolean  prof;
extern boolean  delete_after_append;

/* list command flags */
extern boolean  verbose_listing;

/* extract/print command flags */
extern boolean  output_to_stdout;

/* add/update/delete command flags */
extern boolean  new_archive;
extern boolean  update_if_newer;
extern boolean  generic_format;


/*----------------------------------------------------------------------*/
/*                      VARIABLES                                       */
/*----------------------------------------------------------------------*/

extern char     **cmd_filev;
extern int      cmd_filec;

extern char     *archive_name;
extern char     expanded_archive_name[FILENAME_LENGTH];
extern char     temporary_name[FILENAME_LENGTH];
extern char     backup_archive_name[FILENAME_LENGTH];

extern char *reading_filename, *writting_filename;
extern boolean  remove_temporary_at_error;
extern boolean  recover_archive_when_interrupt;
extern boolean  remove_extracting_file_when_interrupt;

extern int      archive_file_mode;
extern int      archive_file_gid;

/*----------------------------------------------------------------------*/
/*              Functions                                               */
/*----------------------------------------------------------------------*/

extern int interrupt ();

extern void message ();
extern void warning ();
extern void error ();
extern void fatal_error ();

extern boolean need_file ();
extern int inquire ();
extern FILE *xfopen ();

extern boolean find_files ();
extern void free_files ();

extern void init_sp ();
extern void add_sp ();
extern void finish_sp ();
extern void free_sp ();
extern void cleaning_files ();

extern void build_temporary_name ();
extern void build_backup_file_name ();
extern void build_standard_archive_name ();

extern FILE *open_old_archive ();
extern void init_header ();
extern boolean get_header ();
extern boolean archive_is_msdos_sfx1 ();
extern boolean skip_msdos_sfx1_code ();
extern void write_header ();
extern void write_archive_tail ();
extern void copy_old_one ();

extern void cmd_list (), extract_one (), cmd_add (), cmd_delete ();
extern void cmd_extract ();
