/*************************************************
LHarc version 1.13b (c)Yoshi, 1988-89.
main module : 1989/ 5/14
HTAB = 4
*************************************************/
#include <stdio.h>
#include <io.h>
#include <ctype.h>
#include <string.h>
#include <dir.h>
#include <dos.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <stdlib.h>
#include <errno.h>
#define UNKNOWNERR 0
#define INVCMDERR 1
#define MANYPATERR 2
#define NOARCNMERR 3
#define NOFNERR 4
#define NOARCERR 5
#define RENAMEERR 6
#define MKTMPERR 7
#define DUPFNERR 8
#define TOOMANYERR 9
#define TOOLONGERR 10
#define NOFILEERR 11
#define MKFILEERR 12
#define RDERR 13
#define WTERR 14
#define MEMOVRERR 15
#define INVSWERR 16
#define CTRLBRK 17
#define NOMATCHERR 18
#define COPYERR 19
#define NOTLZH 20
#define OVERWT 21
#define MKDIR 22
#define MKDIRERR 23
#define CRCERR 24
#define RDONLY 25
#define MAXBLK 64
#define MAX_PAT 64
#define FAULT 0
#define SUCCS ~FAULT
#define getch() (bdos(0x08, 0, 0) & 0xff)
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
FILE *file1, *file2, *file3, *infile, *outfile;
int cmd; /* command */
int cmdupdate; /* Not zero, when updating archive */
int errorlevel = 0; /* return value */
long textsize; /* file size before compression */
long codesize; /* file size after compression */
long arcpos0; /* position pointer for archive */
uchar *basedir; /* base directory (home-directory) */
uchar *wdir = ""; /* work directory */
uchar workdir[MAXPATH]; /* work directory */
uchar *infname; /* input file name (for error message) */
uchar *outfname; /* output file name (for error message)*/
int attr; /* file attributes for search files */
int Nfile; /* number of files which was found */
int fblft, fbsize; /* for buffers handling file names */
uint seg; /* beginning segment of file name buffers */
uchar far *fbuf, huge *fbnxt; /* pointer to file name buffers */
uchar arcname[MAXPATH]; /* archive name */
uchar pathname[MAXPATH]; /* work for file name (extracting) */
uchar filename[MAXPATH]; /* work for file name (for file in archive) */
int patno; /* No. of path names in command line */
uchar patfile[MAX_PAT][12]; /* file name in command line */
uchar *patpath[MAX_PAT]; /* directory name in command line */
int patcnt[MAX_PAT]; /* counts which this name matched */
uchar patnul[] = "*.*"; /* default path name */
uchar backup1[MAXPATH], backup2[MAXPATH];
/* temporary file names */
uchar flg_r = 0, flg_p = 0, flg_x = 0, flg_m = 0;
uchar flg_a = 0, flg_c = 0, flg_v = 0, flg_w = 0;
uchar flg_n = 0, flg_t = 0;
/* switches */
uchar copying = 0; /* turn on when copying temporary file */
uchar crcflg = 0; /* force copyfile() to calculate CRC*/
uchar tstflg = 0; /* turn on in 't' command */
uchar swchar; /* switch character */
uchar *pager = "less"; /* utility used in 'p /v' mode */
uint crc; /* calculated CRC code */
uchar *keyword = ""; /* key word for auto-execution */
struct filebuf { /* work for file name buffer */
void far *next;
uchar fpos; /* position of file name */
uchar cpos; /* position of effective path name */
uchar dir[MAXDIR]; /* full path name */
} fb0, fb1;
extern char *errmes[]; /* array of pointers to error messages */
extern uchar use[]; /* usage */
extern uchar buf2[], buf3[]; /* I/O buffers */
/* routines for handling Japanese strings */
extern uchar *j_strupr(uchar *p);
extern int j_strcmp(char *p, char *q);
extern uchar *j_strchr(char *p, uint c);
extern uchar *j_strrchr(char *p, uint c);
extern int getfattr(uchar *fn); /* get file attributes */
extern void setfattr(uchar *fn, int attr);/* set file attributes */
extern uchar getswchar(void); /* get switch character */
extern void slash2yen(uchar *p); /* convert '/' to '\' */
extern char M_NOMATCHERR[];
extern char M_COPYERR[];
extern char M_NOTLZH[];
extern char M_OVERWT[];
extern char M_MKDIR[];
extern char M_MKDIRERR[];
extern char M_CRCERR[];
extern char M_RDONLY[];
union stamp { /* time stamp */
struct ftime s;
ulong u;
};
union stamp arcstamp = {0L}; /* time stamp for archive */
struct LzHead { /* file header */
uchar HeadSiz, HeadChk, HeadID[5];
ulong PacSiz, OrgSiz;
union stamp Ftime;
uint Attr;
uchar Fname[MAXPATH];
} Hdr1, Hdr2;
struct exeHead { /* EXE header for SFX */
uint exeID, byte, page, reloc;
uint hdrsize, minalloc, maxalloc, initSS;
uint initSP, chksum, initIP, initCS;
uint reloctab, overlay, dummy1, dummy2;
} ExeHdr = {
'MZ', 0, 0, 0, 2, 0, 0xffff, 0xfff0,
0x100, 0, 0x100, 0xfff0, 0x1e, 0, 0, 0
};
/*******************************
display helps
*******************************/
void usage(void)
{
fputs(use, stdout);
exit(0);
}
/*******************************
display a message
*******************************/
void message(uchar *p, uchar *q)
{
printf("%s", p);
if (q) {
printf(" : '%s'", q);
}
printf("\n");
}
/*******************************
process for an error
*******************************/
void error(int errcode, uchar *p)
{
if (copying) { /* error during copying temporary? */
fprintf(stderr, "\n%s\n", M_COPYERR);
fclose(file1);
unlink(arcname); /* erase incomplete archive */
file1 = NULL;
}
fprintf(stderr, "\n%s", errmes[errcode]);
if (p) {
fprintf(stderr, " : '%s'", p);
}
fprintf(stderr, "\n");
if (file3) {
fclose(file3);
if (!cmdupdate) /* during extracting */
unlink(pathname); /* delete the file */
}
if (file1) {
fclose(file1);
if (cmdupdate) /* during updating */
rename(backup1, arcname); /* recover old archive */
}
if (file2) {
fclose(file2);
if (!copying) { /* if not copying */
unlink(backup2); /* delete temporary */
}
}
if (copying)
exit(3);
else
exit(2);
}
/*******************************
handle user break
*******************************/
int userbreak(void)
{
error(CTRLBRK, NULL);
}
/*******************************
fopen with detecting error
*******************************/
FILE *e_fopen(uchar *fname, uchar *mode, int errID)
{
FILE *f;
if ((f = fopen(fname, mode)) == NULL) {
if (errno == EACCES)
error(RDONLY, fname);
error(errID, fname);
}
return f;
}
/*******************************
rename with detecting error
*******************************/
void e_rename(uchar *old, uchar *new)
{
if (rename(old, new))
error(RENAMEERR, old);
}
/*******************************
ask 'Y' or 'N'
*******************************/
uint getyn(void)
{
uint yn;
do {
yn = toupper(getch());
} while (yn != 'Y' && yn != 'N');
fprintf(stderr, "%c\n", yn);
return yn;
}
/*******************************
file name -> internal format
*******************************/
void extfn(uchar *p, uchar *pb)
{
int i;
uchar * q;
if ((q = j_strrchr(p, '\\')) != NULL ||
(q = j_strchr(p, ':')) != NULL)
p = q + 1;
q = p;
for (i = 8; i > 0; i--, pb++) {
switch (*p) {
case '*':
*pb = '?';
break;
case '.':
case '\0':
*pb = ' ';
break;
default:
*pb = *p++;
}
}
while (+(*p != '\0' && *p++ != '.'));
for (i = 3; i > 0; i--, pb++) {
switch (*p) {
case '*':
*pb = '?';
break;
case '\0':
*pb = ' ';
break;
default:
*pb = *p++;
}
}
*q = *pb = '\0';
}
/*******************************
internal format -> file name
*******************************/
void packfn(uchar *p, uchar *q)
{
int i;
for (i = 8; i > 0; i--) {
if (*q != ' ')
*p++ = *q;
q++;
}
*p++ = '.';
for (i = 3; i > 0; i--) {
if (*q != ' ')
*p++ = *q;
q++;
}
if (p[-1] ==