$PART2:
$ CALL UNPACK [.UNARJ_SRC]OS2UNARJ.MAK;1 706033648
$ create 'f'
X# MAKE file for unarj.exe for QuickC QCL
X
XCC=qcl -AS -W4
X
Xall:`09      unarj.exe
X
Xunarj.obj:    unarj.c`09unarj.h
X
Xenviron.obj:  environ.c unarj.h
X
Xdecode.obj:   decode.c`09unarj.h
X
Xunarj.exe:    unarj.obj decode.obj environ.obj
X       qcl    unarj.obj decode.obj environ.obj
X
X# end of make
$ CALL UNPACK [.UNARJ_SRC]QCLUNARJ.MAK;1 806387149
$ create 'f'
X
X   README.DOC`09`09`09`09`09      June 1991
X
X
X   This archive contains UNARJ version 2.20.
X
X   This software as originally released by the author came in an ARJ
X   self-extracting archive with an ARJ-SECURITY envelope to prevent
X   tampering.  Re-archival of this software will lose this security
X   feature.
X
X
X   THIS ARCHIVE CONTAINS THE FOLLOWING FILES:
X
X   UNARJ220.EXE - An ARJ-SECURED self-extracting archive containing the
X`09`09  following files:
X
X                  README.DOC     - this file
X                  UNARJ.EXE      - UNARJ executable for MS-DOS
X                  UNARJ.DOC      - ARJ user manual
X                  UNARJ.C        - C source file
X                  DECODE.C       - C source file
X                  ENVIRON.C      - C source file
X                  UNARJ.H        - C include file
X                  UNARJ.DEF      - OS/2 definition file
X                  TCCUNARJ.MAK   - TCC make file
X                  QCLUNARJ.MAK   - QuickC make file
X                  OS2UNARJ.MAK   - OS/2 Microsoft make file
X                  TECHNOTE.DOC   - technical information about ARJ
X
X   To verify the ARJ-SECURITY envelope and contents of UNARJ220.EXE, type:
X
X      UNARJ220 -t
X
X   To extract the files in UNARJ220.EXE, type:
X
X      UNARJ220
X
X      This will extract the files in UNARJ220.EXE to the current
X      directory.
X
X   To extract the files in UNARJ220.EXE using ARJ.EXE:
X
X      ARJ e UNARJ220.EXE
X
X   For users with unusual DOS systems (not 2.11, 3.2, 3.3, 4.0), you may
X   have to rename UNARJ220.EXE to ARJSFX.EXE to do the extraction.
X
X   end of readme.doc
X
$ CALL UNPACK [.UNARJ_SRC]README.DOC;1 929446134
$ create 'f'
X# MAKE file for unarj.exe for Turbo C
X
Xunarj.exe:    unarj.obj decode.obj environ.obj
X
X       tcc -M unarj.obj decode.obj environ.obj
X
Xunarj.obj:    unarj.c`09unarj.h
X
Xenviron.obj:  environ.c unarj.h
X
Xdecode.obj:   decode.c`09unarj.h
X
X.c.obj:
X    tcc -c -N -k -G -w -ms $<
X
X# end of make
$ CALL UNPACK [.UNARJ_SRC]TCCUNARJ.MAK;1 103703969
$ create 'f'
X
X     ARJ TECHNICAL INFORMATION`09`09`09`09    June 1991
X
X
X     ** IMPORTANT NEWS ****************************************************
X
X     There is an extended header bug in older versions of ARJ, AV.C and
X     UNARJ.C.  The extended header processing in read_header() should
X     skip 4 bytes for the extended header CRC and not 2.  This is NOT a
X     current problem as no versions of ARJ use the extended header.
X
X     **********************************************************************
X
X
X     Modification history:
X     Date      Description of modification:
X     --------  ------------------------------------------------------
X     06/28/91  Added several new HOST OS numbers.
X     05/19/91  Improved the description of extended header processing.
X     05/11/91  Simplified this document.  Added volume label type.
X     03/11/91  Added directory file type.
X     02/23/91  Added more comments.
X     01/10/91  Corrected timestamp description and header order of file mode
V.
X     10/30/90  Corrected values of flags in ARJ flags.
X
X
X     ARJ archives contains two types of header blocks:
X
X`09Archive main header - This is located at the head of the archive
X`09Local file header   - This is located before each archived file
X
X     Structure of archive block (low order byte first):
X
X     Bytes Description
X     ----- -----------------------------------------------------------------
V--
X       2   header id (main and local file) = 0xEA60 or 60000U
X       2   basic header size (from 'first_hdr_size' thru 'comment' below)
X`09`09 = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
X`09`09 = 0 if end of archive
X
X       1   first_hdr_size (size up to and including 'extra data')
X       1   archiver version number
X       1   minimum archiver version to extract
X       1   host OS   (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC-OS
V)
X`09`09     (5 = OS/2, 6 = APPLE GS, 7 = ATARI ST, 8 = NEXT)
X`09`09     (9 = VAX VMS)
X       1   arj flags (0x01 = GARBLED_FLAG) indicates passworded file
X`09`09     (0x02 = RESERVED)
X`09`09     (0x04 = VOLUME_FLAG)  indicates continued file to next
X`09`09`09`09`09   volume
X`09`09     (0x08 = EXTFILE_FLAG) indicates file starting position
X`09`09`09`09`09   field
X`09`09     (0x10 = PATHSYM_FLAG) indicates path translated
X`09`09`09`09`09   ("\" changed to "/")
X       1   method    (0 = stored, 1 = compressed most ... 4 compressed faste
Vst)
X       1   file type (0 = binary, 1 = 7-bit text, 2 = comment header)
X`09`09     (3 = directory, 4 = volume label)
X       1   reserved
X       4   date time modified
X       4   compressed size
X       4   original size (this will be different for text mode compression)
X       4   original file's CRC
X       2   filespec position in filename
X       2   file access mode
X       2   host data (currently not used)
X       ?   extra data
X`09   4 bytes for extended file starting position when used
X`09   (this is present when EXTFILE_FLAG is set)
X
X       ?   filename (null-terminated string)
X       ?   comment  (null-terminated string)
X
X       4   basic header CRC
X
X       2   1st extended header size (0 if none)
X       ?   1st extended header (currently not used)
X       4   1st extended header's CRC (not present when 0 extended header siz
Ve)
X
X       ...
X
X       ?   compressed file
X
X
X     Time stamp format:
X
X`0931 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
X       `7C<---- year-1980 --->`7C<- month ->`7C<--- day ---->`7C
X
X`0915 14 13 12 11 10  9  8  7  6  5  4  3`092  1  0
X       `7C<--- hour --->`7C<---- minute --->`7C<- second/2 ->`7C
X
X
X
X     Compression methods:
X
X
X     ARJ methods 1 to 3 use Lempel-Ziv 77 sliding window with static Huffman
X     encoding.
X
X     ARJ method 4 uses Lempel-Ziv 77 sliding window with pointer/length
X     unary encoding.
X
X     There is one decoder for methods 1 to 3 and one decoder for method 4.
X
X
X
X     Encryption technology:
X
X
X     ARJ does NOT use DES encryption algorithms.  It uses a combination of
X     simple exclusive-or operations.
X
X
X     end of document
X
$ CALL UNPACK [.UNARJ_SRC]TECHNOTE.DOC;1 1375928889
$ create 'f'
X/* UNARJ.C, UNARJ, R JUNG, 07/07/91
X * Main Extractor routine
X * Copyright (c) 1991 by Robert K Jung.  All rights reserved.
X *
X *   This code may be freely used in programs that are NOT ARJ archivers
X *   (both compress and extract ARJ archives).
X *
X *   If you wish to distribute a modified version of this program, you
X *   MUST indicate that it is a modified version both in the program and
X *   source code.
X *
X *   If you modify this program, I would appreciate a copy of the new
X *   source code.  I am holding the copyright on the source code, so
X *   please do not delete my name from the program files or from the
X *   documentation.
X *
X *   I wish to give credit to Haruhiko Okumura for providing the
X *   basic ideas for ARJ and UNARJ in his program AR.  Please note
X *   that UNARJ is significantly different from AR from an archive
X *   structural point of view.
X *
X * Modification history:
X * Date      Programmer  Description of modification.
X * 04/05/91  R. Jung`09 Rewrote code.
X * 04/23/91  M. Adler`09 Portabilized.
X * 04/29/91  R. Jung`09 Added l command.  Removed 16 bit dependency in
X *`09`09`09 fillbuf().
X * 05/19/91  R. Jung`09 Fixed extended header skipping code.
X * 05/25/91  R. Jung`09 Improved find_header().
X * 06/03/91  R. Jung     Changed arguments in get_mode_str() and
X *                       set_ftime_mode().
X * 06/19/81  R. Jung     Added two more %c in printf() in list_arc().
X * 07/07/91  R. Jung     Added default_case_path() to extract().
X *                       Added strlower().
X *
X */
X
X#include "unarj.h"
X
X#define DEBUG
X
X#ifdef MODERN
X#include <stdlib.h>
X#include <string.h>
X#include <ctype.h>
X#else /* !MODERN */
Xextern void free();
Xextern void exit();
Xextern char *strcat();
Xextern char *strcpy();
Xextern char *strncpy();
Xextern char *strchr();
Xextern char *strrchr();
Xextern int strlen();
Xextern int strcmp();
X
X#ifndef VMS
X#define EXIT_FAILURE (1)
X#define EXIT_SUCCESS (0)
X#else`09/* VMS */
X#define EXIT_FAILURE (0)
X#define EXIT_SUCCESS (1)
X#endif  /* ?VMS */
X
X#define toupper(c)   ((c)>='a'&&(c)<='z'?(c)-('a'-'A'):(c))
X#define tolower(c)   ((c)>='A'&&(c)<='Z'?(c)+('a'-'A'):(c))
X#endif /* ?MODERN */
X
X/* Global variables */
X
XUCRC   crc;
XFILE   *arcfile;
XFILE   *outfile;
Xushort bitbuf;
Xlong   compsize;
Xlong   origsize;
Xuchar  subbitbuf;
Xuchar  header`5BHEADERSIZE_MAX`5D;
Xchar   arc_name`5BFNAME_MAX`5D;
Xint    command;
Xint    bitcount;
Xint    file_type;
Xint    no_output;
Xint    error_count;
X
X/* Messages */
X
Xstatic char *M_USAGE  `5B`5D =
X`7B
X"Usage:  UNARJ archive`5B.arj`5D    (list archive)\n",
X"        UNARJ e archive        (extract archive)\n",
X"        UNARJ l archive        (list archive)\n",
X"        UNARJ t archive        (test archive)\n",
X"        UNARJ x archive        (extract with pathnames)\n",
X"\n",
X"This is an ARJ demonstration program and ** IS NOT OPTIMIZED ** for speed.\
Vn",
X"You may freely use, copy and distribute this program, provided that no fee\
Vn",
X"is charged for such use, copying or distribution, and it is distributed\n",
X"ONLY in its original unmodified state.  UNARJ is provided as is without\n",
X"warranty of any kind, express or implied, including but not limited to\n",
X"the implied warranties of merchantability and fitness for a particular\n",
X"purpose.  Refer to UNARJ.DOC for more warranty information.  If you find\n"
V,
X"UNARJ of value, a gift of $10 or any amount would greatly appreciated.\n",
X"\n",
X"Robert K Jung                   Internet address :  robjung@world.std.com\n
V",
X"2606 Village Road West          CompuServe userid:  72077,445\n",
X"Norwood, Massachusetts 02062\n",
X"USA\n",
XNULL
X`7D;
X
Xchar M_VERSION `5B`5D = "UNARJ (Demo version) 2.20 Copyright (c) 1991 Robert
V K Jung\n\n";
X
Xchar M_ARCDATE `5B`5D = "Archive date      : %s\n";
Xchar M_BADCOMND`5B`5D = "Bad UNARJ command: %s";
Xchar M_BADCOMNT`5B`5D = "Invalid comment header";
Xchar M_BADHEADR`5B`5D = "Bad header";
Xchar M_BADTABLE`5B`5D = "Bad Huffman code";
Xchar M_CANTOPEN`5B`5D = "Can't open %s";
Xchar M_CANTREAD`5B`5D = "Can't read file or unexpected end of file";
Xchar M_CANTWRIT`5B`5D = "Can't write file. Disk full?";
Xchar M_CRCERROR`5B`5D = "CRC error!\n";
Xchar M_CRCOK   `5B`5D = "CRC OK\n";
Xchar M_DIFFHOST`5B`5D = ", Warning! Binary file from a different OS";
Xchar M_ENCRYPT `5B`5D = "File is password encrypted, ";
Xchar M_ERRORCNT`5B`5D = "%sFound %5d error(s)!";
Xchar M_EXTRACT `5B`5D = "Extracting %-25s";
Xchar M_FEXISTS `5B`5D = "%-25s exists, ";
Xchar M_HEADRCRC`5B`5D = "Header CRC error!";
Xchar M_NBRFILES`5B`5D = "%5d file(s)\n";
Xchar M_NOMEMORY`5B`5D = "Out of memory";
Xchar M_NOTARJ  `5B`5D = "%s is not an ARJ archive";
Xchar M_PROCARC `5B`5D = "Processing archive: %s\n";
Xchar M_SKIPPED `5B`5D = "Skipped %s\n";
Xchar M_SUFFIX  `5B`5D = ARJ_SUFFIX;
Xchar M_TESTING `5B`5D = "Testing    %-25s";
Xchar M_UNKNMETH`5B`5D = "Unsupported method: %d, ";
Xchar M_UNKNTYPE`5B`5D = "Unsupported file type: %d, ";
Xchar M_UNKNVERS`5B`5D = "Unsupported version: %d, ";
X
X#define get_crc()`09get_longword()
X#define fget_crc(f)`09fget_longword(f)
X
X#define setup_get(PTR)`09(get_ptr = (PTR))
X#define get_byte()`09((uchar)(*get_ptr++ & 0xff))
X
X#define BUFFERSIZE`094096
X
X#define ASCII_MASK`090x7F
X
X#define CRCPOLY `090xEDB88320L
X
X#define UPDATE_CRC(r,c) r=crctable`5B((uchar)(r)`5E(uchar)(c))&0xff`5D`5E(r>
V>CHAR_BIT)
X
X/* Local functions */
X
X#ifdef MODERN
Xstatic void  make_crctable(void);
Xstatic void  crc_buf(char *str, int len);
Xstatic void  strparity(uchar *p);
Xstatic FILE  *fopen_msg(char *name, char *mode);
Xstatic int   fget_byte(FILE *f);
Xstatic uint  fget_word(FILE *f);
Xstatic ulong fget_longword(FILE *f);
Xstatic void  fread_crc(uchar *p, int n, FILE *f);
Xstatic void  decode_path(char *name);
Xstatic void  get_date_str(char *str, ulong tstamp);
Xstatic int   parse_path(char *pathname, char *path, char *entry);
Xstatic void  strncopy(char *to, char *from, int len);
Xstatic uint  get_word(void);
Xstatic ulong get_longword(void);
Xstatic long  find_header(FILE *fd);
Xstatic int   read_header(int first, FILE *fd, char *name);
Xstatic void  skip(void);
Xstatic void  unstore(void);
Xstatic int   check_flags(void);
Xstatic int   extract(void);
Xstatic int   test(void);
Xstatic uint  ratio(long a, long b);
Xstatic void  list_start(void);
Xstatic void  list_arc(int count);
Xstatic void  execute_cmd(void);
Xstatic void  help(void);
X#endif /* MODERN */
X
X/* Local variables */
X
Xstatic char   filename`5BFNAME_MAX`5D;
Xstatic char   comment`5BCOMMENT_MAX`5D;
Xstatic char   *hdr_filename;
Xstatic char   *hdr_comment;
X
Xstatic ushort headersize;
Xstatic uchar  first_hdr_size;
Xstatic uchar  arj_nbr;
Xstatic uchar  arj_x_nbr;
Xstatic uchar  host_os;
Xstatic uchar  arj_flags;
Xstatic short  method;
Xstatic uint   file_mode;
Xstatic ulong  time_stamp;
Xstatic short  entry_pos;
Xstatic ushort host_data;
Xstatic uchar  *get_ptr;
Xstatic UCRC   file_crc;
Xstatic UCRC   header_crc;
X
Xstatic long   first_hdr_pos;
Xstatic long   torigsize;
Xstatic long   tcompsize;
X
Xstatic int    clock_inx;
X
Xstatic char   *writemode`5B2`5D  = `7B "wb",`09"w" `7D;
X
Xstatic UCRC   crctable`5BUCHAR_MAX + 1`5D;
X
X/* Functions */
X
Xstatic void
Xmake_crctable()
X`7B
X    uint i, j;
X    UCRC r;
X
X    for (i = 0; i <= UCHAR_MAX; i++)
X    `7B
X`09r = i;
X`09for (j = CHAR_BIT; j > 0; j--)
X`09`7B
X`09    if (r & 1)
X`09`09r = (r >> 1) `5E CRCPOLY;
X`09    else
X`09`09r >>= 1;
X`09`7D
X`09crctable`5Bi`5D = r;
X    `7D
X`7D
X
Xstatic void
Xcrc_buf(str, len)
Xchar *str;
Xint  len;
X`7B
X    while (len--)
X`09UPDATE_CRC(crc, *str++);
X`7D
X
Xvoid
Xdisp_clock()
X`7B
X    static char clock_str`5B4`5D = `7B '`7C', '/', '-', '\\' `7D;
X
X    printf("(%c)\b\b\b", clock_str`5Bclock_inx`5D);
X    clock_inx = (clock_inx + 1) & 0x03;
X`7D
X
Xvoid
Xerror(fmt, arg)
Xchar *fmt;
Xchar *arg;
X`7B
X    putc('\n', stdout);
X    printf(fmt, arg, error_count);
X    putc('\n', stdout);
X    exit(EXIT_FAILURE);
X`7D
X
Xstatic void
Xstrparity(p)
Xuchar *p;
X`7B
X    while (*p)
X    `7B
X`09FIX_PARITY(*p);
X`09p++;
X    `7D
X`7D
X
Xstatic FILE *
Xfopen_msg(name, mode)
Xchar *name;
Xchar *mode;
X`7B
X    FILE *fd;
X
X    fd = file_open(name, mode);
X    if (fd == NULL)
X`09error(M_CANTOPEN, name);
X    return fd;
X`7D
X
Xstatic int
Xfget_byte(f)
XFILE *f;
X`7B
X    int c;
X
X/*
X    if ((c = getc(f)) == EOF)
X*/
X    if( fread(&c,1,1,f) != 1 )
X`09error(M_CANTREAD, "");
X    return c & 0xFF;
X`7D
X
Xstatic uint
Xfget_word(f)
XFILE *f;
X`7B
X    uint b0, b1;
X
X    b0 = fget_byte(f);
X    b1 = fget_byte(f);
X    return (b1 << 8) + b0;
X`7D
X
Xstatic ulong
Xfget_longword(f)
XFILE *f;
X`7B
X    ulong b0, b1, b2, b3;
X
X    b0 = fget_byte(f);
X    b1 = fget_byte(f);
X    b2 = fget_byte(f);
X    b3 = fget_byte(f);
X    return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
X`7D
X
Xstatic void
Xfread_crc(p, n, f)
Xuchar *p;
Xint   n;
XFILE  *f;
X`7B
X    n = file_read((char *)p, 1, n, f);
X    origsize += n;
X    crc_buf((char *)p, n);
X`7D
X
Xvoid
Xfwrite_txt_crc(p, n)
Xuchar *p;
Xint   n;
X`7B
X    uchar c;
X
X    crc_buf((char *)p, n);
X    if (no_output)
X`09return;
X
X    if (file_type == TEXT_TYPE)
X    `7B
X`09while (n--)
X`09`7B
X`09    c = *p++;
X`09    FIX_PARITY(c);
X`09    if (putc((int) c, outfile) == EOF)
X`09`09error(M_CANTWRIT, "");
X`09`7D
X    `7D
X    else
X    `7B
X`09if (file_write((char *)p, 1, n, outfile) != n)
X`09    error(M_CANTWRIT, "");
X    `7D
X`7D
X
Xvoid
Xinit_getbits()
X`7B
X    bitbuf = 0;
X    subbitbuf = 0;
X    bitcount = 0;
X    fillbuf(2 * CHAR_BIT);
X`7D
X
Xvoid
Xfillbuf(n)`09`09  /* Shift bitbuf n bits left, read n bits */
Xint n;
X`7B
X    bitbuf = (bitbuf << n) & 0xFFFF;  /* lose the first n bits */
X    while (n > bitcount)
X    `7B
X`09bitbuf `7C= subbitbuf << (n -= bitcount);
X`09if (compsize != 0)
X`09`7B
X`09    compsize--;
X`09    subbitbuf = (uchar) getc(arcfile);
X`09`7D
X`09else
X`09    subbitbuf = 0;
X`09bitcount = CHAR_BIT;
X    `7D
X    bitbuf `7C= subbitbuf >> (bitcount -= n);
X`7D
X
Xushort
Xgetbits(n)
Xint n;
X`7B
X    ushort x;
X
X    x = bitbuf >> (2 * CHAR_BIT - n);
X    fillbuf(n);
X    return x;
X`7D
X
Xstatic void
Xdecode_path(name)
Xchar *name;
X`7B
X    for ( ; *name; name++)
X    `7B
X`09if (*name == ARJ_PATH_CHAR)
X`09    *name = PATH_CHAR;
X    `7D
X`7D
X
Xstatic void
Xget_date_str(str, tstamp)
Xchar  *str;
Xulong tstamp;
X`7B
X    sprintf(str, "%04u-%02u-%02u %02u:%02u:%02u",
X`09   ts_year(tstamp), ts_month(tstamp), ts_day(tstamp),
X`09   ts_hour(tstamp), ts_min(tstamp), ts_sec(tstamp));
X`7D
X
Xstatic int
Xparse_path(pathname, path, entry)
Xchar *pathname;
Xchar *path;
Xchar *entry;
X`7B
X    char *cptr, *ptr, *fptr;
X    short pos;
X
X    fptr = NULL;
X    for (cptr = PATH_SEPARATORS; *cptr; cptr++)
X    `7B
X`09if ((ptr = strrchr(pathname, *cptr)) != NULL &&
X`09`09(fptr == NULL `7C`7C ptr > fptr))
X`09    fptr = ptr;
X    `7D
X    if (fptr == NULL)
X`09pos = 0;
X    else
X`09pos = fptr + 1 - pathname;
X    if (path != NULL)
X    `7B
X       strncpy(path, pathname, pos);
X       path`5Bpos`5D = NULL_CHAR;
X    `7D
X    if (entry != NULL)
X       strcpy(entry, &pathname`5Bpos`5D);
X    return pos;
X`7D
X
Xstatic void
Xstrncopy(to, from, len)
Xchar *to;
Xchar *from;
Xint  len;
X`7B
X    int i;
X
X    for (i = 1; i < len && *from; i++)
X`09*to++ = *from++;
X    *to = NULL_CHAR;
X`7D
X
Xvoid
Xstrlower(s)
Xchar *s;
X`7B
X    while (*s)
X    `7B
X        *s = (char) tolower(*s);
X`09s++;
X    `7D
X`7D
X
Xvoid
Xstrupper(s)
Xchar *s;
X`7B
X    while (*s)
X    `7B
X        *s = (char) toupper(*s);
X`09s++;
X    `7D
X`7D
X
Xvoidp *
Xmalloc_msg(size)
Xint size;
X`7B
X    char *p;
X
X    if ((p = (char *)xmalloc(size)) == NULL)
X`09error(M_NOMEMORY, "");
X    return (voidp *)p;
X`7D
X
Xstatic uint
Xget_word()
X`7B
X    uint b0, b1;
X
X    b0 = get_byte();
X    b1 = get_byte();
X    return (b1 << 8) + b0;
X`7D
X
Xstatic ulong
Xget_longword()
X`7B
X    ulong b0, b1, b2, b3;
X
X    b0 = get_byte();
X    b1 = get_byte();
X    b2 = get_byte();
X    b3 = get_byte();
X    return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
X`7D
X
Xstatic long
Xfind_header(fd)
XFILE *fd;
X`7B
X    long arcpos, lastpos;
X    int c;
X
X    arcpos = file_tell(fd);
X    file_seek(fd, 0L, SEEK_END);
X    lastpos = file_tell(fd) - 2;
X    if (lastpos > MAXSFX)
X`09lastpos = MAXSFX;
X    for ( ; arcpos < lastpos; arcpos++)
X    `7B
X`09file_seek(fd, arcpos, SEEK_SET);
X`09c = fget_byte(fd);
X`09while (arcpos < lastpos)
X`09`7B
X`09    if (c != HEADER_ID_LO)  /* low order first */
X`09`09c = fget_byte(fd);
X`09    else if ((c = fget_byte(fd)) == HEADER_ID_HI)
X`09`09break;
X`09    arcpos++;
X`09`7D
X`09if (arcpos >= lastpos)
X`09    break;
X`09if ((headersize = fget_word(fd)) <= HEADERSIZE_MAX)
X`09`7B
X`09    crc = CRC_MASK;
X`09    fread_crc(header, (int) headersize, fd);
X`09    if ((crc `5E CRC_MASK) == fget_crc(fd))
X`09    `7B
X`09`09file_seek(fd, arcpos, SEEK_SET);
X`09`09return arcpos;
X`09    `7D
X`09`7D
X    `7D
X    return -1;`09`09/* could not find a valid header */
X`7D
X
Xstatic int
Xread_header(first, fd, name)
Xint  first;
XFILE *fd;
Xchar *name;
X`7B
X    ushort extheadersize, header_id;
X
X    header_id = fget_word(fd);
X    if (header_id != HEADER_ID)
X    `7B
X`09if (first)
X`09    error(M_NOTARJ, name);
X`09else
X`09    error(M_BADHEADR, "");
X    `7D
X
X    headersize = fget_word(fd);
X    if (headersize == 0)
X`09return 0;`09`09/* end of archive */
X    if (headersize > HEADERSIZE_MAX)
X`09error(M_BADHEADR, "");
X
X    crc = CRC_MASK;
X    fread_crc(header, (int) headersize, fd);
X    header_crc = fget_crc(fd);
X    if ((crc `5E CRC_MASK) != header_crc)
X`09error(M_HEADRCRC, "");
X
X    setup_get(header);
X    first_hdr_size = get_byte();
X    arj_nbr = get_byte();
X    arj_x_nbr = get_byte();
X    host_os = get_byte();
X    arj_flags = get_byte();
X    method = get_byte();
X    file_type = get_byte();
X    (void)get_byte();
X    time_stamp = get_longword();
X    compsize = get_longword();
X    origsize = get_longword();
X    file_crc = get_crc();
X    entry_pos = get_word();
X    file_mode = get_word();
X    host_data = get_word();
X
X    hdr_filename = (char *)&header`5Bfirst_hdr_size`5D;
X    strncopy(filename, hdr_filename, sizeof(filename));
X    if (host_os != OS)
X`09strparity((uchar *)filename);
X    if ((arj_flags & PATHSYM_FLAG) != 0)
X`09decode_path(filename);
X
X    hdr_comment = (char *)&header`5Bfirst_hdr_size + strlen(hdr_filename) +
V 1`5D;
X    strncopy(comment, hdr_comment, sizeof(comment));
X    if (host_os != OS)
X`09strparity((uchar *)comment);
X
X    /* if extheadersize == 0 then no CRC */
X    /* otherwise read extheader data and read 4 bytes for CRC */
X
X    while ((extheadersize = fget_word(fd)) != 0)
X`09file_seek(fd, (long) (extheadersize + 4), SEEK_CUR);
X
X    return 1;`09`09`09/* success */
X`7D
X
Xstatic void
Xskip()
X`7B
X    file_seek(arcfile, compsize, SEEK_CUR);
X`7D
X
Xstatic void
Xunstore()
X`7B
X    int n;
X    long pos;
X    char *buffer;
X
X    buffer = (char *)malloc_msg(BUFFERSIZE);
X    pos = file_tell(arcfile);
X    disp_clock();
X    n = (int)(BUFFERSIZE - (pos % BUFFERSIZE));
X    n = compsize > (long)n ? n : (int)compsize;
X    while (compsize > 0)
X    `7B
X`09if (file_read(buffer, 1, n, arcfile) != n)
X`09    error(M_CANTREAD, "");
X`09disp_clock();
X`09compsize -= n;
X`09fwrite_txt_crc((uchar *)buffer, n);
X`09n = compsize > BUFFERSIZE ? BUFFERSIZE : (int)compsize;
X    `7D
X    free(buffer);
X`7D
X
Xstatic int
Xcheck_flags()
X`7B
X    if (arj_x_nbr > ARJ_X_VERSION)
X    `7B
X`09printf(M_UNKNVERS, arj_x_nbr);
X`09printf(M_SKIPPED, filename);
X`09skip();
X`09return -1;
X    `7D
X    if ((arj_flags & GARBLE_FLAG) != 0)
X    `7B
X`09printf(M_ENCRYPT);
X`09printf(M_SKIPPED, filename);
X`09skip();
X`09return -1;
X    `7D
X    if (method < 0 `7C`7C method > MAXMETHOD `7C`7C (method == 4 && arj_nbr
V == 1))
X    `7B
X`09printf(M_UNKNMETH, method);
X`09printf(M_SKIPPED, filename);
X`09skip();
X`09return -1;
X    `7D
X    if (file_type != BINARY_TYPE && file_type != TEXT_TYPE)
X    `7B
X`09printf(M_UNKNTYPE, file_type);
X`09printf(M_SKIPPED, filename);
X`09skip();
X`09return -1;
X    `7D
X    return 0;
X`7D
X
Xstatic int
Xextract()
X`7B
X    char name`5BFNAME_MAX`5D;
X
X    if (check_flags())
X`09return 0;
X
X    no_output = 0;
X    if (command == 'E')
X`09strcpy(name, &filename`5Bentry_pos`5D);
X    else
X    `7B
X`09strcpy(name, DEFAULT_DIR);
X`09strcat(name, filename);
X    `7D
X
X    if (host_os != OS)
X        default_case_path(name);
X
X    if (file_exists(name))
X    `7B
X`09printf(M_FEXISTS, name);
X`09printf(M_SKIPPED, name);
X`09skip();
X`09return 0;
X    `7D
X    outfile = file_open(name, writemode`5Bfile_type & 1`5D);
X    if (outfile == NULL)
X    `7B
X`09printf(M_CANTOPEN, name);
X`09putchar('\n');
X`09skip();
X`09return 0;
X    `7D
X    printf(M_EXTRACT, name);
X    if (host_os != OS && file_type == BINARY_TYPE)
X`09printf(M_DIFFHOST);
X    printf("  ");
X
X    crc = CRC_MASK;
X
X    if (method == 0)
X`09unstore();
X    else if (method == 1 `7C`7C method == 2 `7C`7C method == 3)
X`09decode();
X    else if (method == 4)
X`09decode_f();
X    fclose(outfile);
X
X    set_ftime_mode(name, time_stamp, file_mode, (uint) host_os);
X
X    if ((crc `5E CRC_MASK) == file_crc)
X`09printf(M_CRCOK);
X    else
X    `7B
X`09printf(M_CRCERROR);
X`09error_count++;
X    `7D
X    return 1;
X`7D
X
Xstatic int
Xtest()
X`7B
X    if (check_flags())
X`09return 0;
X
X    no_output = 1;
X    printf(M_TESTING, filename);
X    printf("  ");
X
X    crc = CRC_MASK;
X
X    if (method == 0)
X`09unstore();
X    else if (method == 1 `7C`7C method == 2 `7C`7C method == 3)
X`09decode();
X    else if (method == 4)
X`09decode_f();
X
X    if ((crc `5E CRC_MASK) == file_crc)
X`09printf(M_CRCOK);
X    else
X    `7B
X`09printf(M_CRCERROR);
X`09error_count++;
X    `7D
X    return 1;
X`7D
X
Xuint
Xratio(a, b)
Xlong a, b;
X`7B
X   int i;
X
X   for (i = 0; i < 3; i++)
X       if (a <= LONG_MAX / 10)
X`09   a *= 10;
X       else
X`09   b /= 10;
X   if ((long) (a + (b >> 1)) < a)
X   `7B
X       a >>= 1;
X       b >>= 1;
X   `7D
X   if (b == 0)
X       return 0;
X   return (uint) ((a + (b >> 1)) / b);
X`7D
X
Xstatic void
Xlist_start()
X`7B
X    printf("Filename       Original Compressed Ratio DateTime modified CRC-3
V2   Attr TPMGVX\n");
X    printf("------------ ---------- ---------- ----- ----------------- -----
V--- ---- ------\n");
X`7D
X
Xstatic void
Xlist_arc(count)
Xint count;
X`7B
X    uint r;
X    int garble_mode, path_mode, volume_mode, extfil_mode, ftype;
X    char date_str`5B20`5D, fmode_str`5B10`5D;
X    static char mode`5B5`5D = `7B 'B', 'T', '?', 'D', 'V' `7D;
X    static char pthf`5B2`5D = `7B ' ', '+' `7D;
X    static char pwdf`5B2`5D = `7B ' ', 'G' `7D;  /* plain, encrypted */
X    static char volf`5B2`5D = `7B ' ', 'V' `7D;
X    static char extf`5B2`5D = `7B ' ', 'X' `7D;
X
X    if (count == 0)
X`09list_start();
X
X    garble_mode = ((arj_flags & GARBLE_FLAG) != 0);
X    volume_mode = ((arj_flags & VOLUME_FLAG) != 0);
X    extfil_mode = ((arj_flags & EXTFILE_FLAG) != 0);
X    path_mode = (entry_pos > 0);
X    r = ratio(compsize, origsize);
X    torigsize += origsize;
X    tcompsize += compsize;
X    ftype = file_type;
X    if (ftype != BINARY_TYPE && ftype != TEXT_TYPE && ftype != DIR_TYPE &&
X`09    ftype != LABEL_TYPE)
X`09ftype = 3;
X    get_date_str(date_str, time_stamp);
X    strcpy(fmode_str, "    ");
X    if (host_os == OS)
X        get_mode_str(fmode_str, (uint) file_mode);
X    if (strlen(&filename`5Bentry_pos`5D) > 12)
X`09printf("%-12s\n             ", &filename`5Bentry_pos`5D);
X    else
X`09printf("%-12s ", &filename`5Bentry_pos`5D);
X    printf("%10ld %10ld %u.%03u %s %08lX %4s %c%c%u%c%c%c\n",
X`09origsize, compsize, r / 1000, r % 1000, &date_str`5B2`5D, file_crc,
X`09fmode_str, mode`5Bftype`5D, pthf`5Bpath_mode`5D, method, pwdf`5Bgarble_mo
Vde`5D,
X`09volf`5Bvolume_mode`5D, extf`5Bextfil_mode`5D);
X`7D
X
Xstatic void
Xexecute_cmd()
X`7B
X    int file_count;
X    char date_str`5B22`5D;
X    uint r;
X
X    first_hdr_pos = 0;
X    time_stamp = 0;
X    first_hdr_size = FIRST_HDR_SIZE;
X
X    arcfile = fopen_msg(arc_name, "rb");
X
X    printf(M_PROCARC, arc_name);
X
X    first_hdr_pos = find_header(arcfile);
X    if (first_hdr_pos < 0)
X`09error(M_NOTARJ, arc_name);
X    file_seek(arcfile, first_hdr_pos, SEEK_SET);
X    if (!read_header(1, arcfile, arc_name))
X`09error(M_BADCOMNT, "");
X    get_date_str(date_str, time_stamp);
X    printf(M_ARCDATE, date_str);
X
X    file_count = 0;
X    while (read_header(0, arcfile, arc_name))
X    `7B
X`09switch (command)
X`09`7B
X`09case 'E':
X`09case 'X':
X`09    if (extract())
X`09`09file_count++;
X`09    break;
X`09case 'L':
X`09    list_arc(file_count++);
X`09    skip();
X`09    break;
X`09case 'T':
X`09    if (test())
X`09`09file_count++;
X`09    break;
X`09`7D
X    `7D
X
X    if (command == 'L')
X    `7B
X`09printf("------------ ---------- ---------- ----- -----------------\n");
X`09r = ratio(tcompsize, torigsize);
X`09printf(" %5d files %10ld %10ld %u.%03u %s\n",
X`09    file_count, torigsize, tcompsize, r / 1000, r % 1000, &date_str`5B2`5
VD);
X    `7D
X    else
X`09printf(M_NBRFILES, file_count);
X
X    fclose(arcfile);
X`7D
X
Xstatic void
Xhelp()
X`7B
X    int i;
X
X    for (i = 0; M_USAGE`5Bi`5D != NULL; i++)
X`09printf(M_USAGE`5Bi`5D);
X`7D
X
Xint
Xmain(argc, argv)
Xint  argc;
Xchar *argv`5B`5D;
X`7B
X    int i, j, lastc;
X    char *arc_p;
X
X    printf(M_VERSION);
X
+-+-+-+-+-+-+-+-  END  OF PART 2 +-+-+-+-+-+-+-+-
