davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (12/06/90)
Here is a versions of lharc I have hacked to run cleanly on a large number of systems, including Xenix, Sun[34], Encore, and Ultrix. #!/bin/sh # shar: Shell Archiver (v1.29) # # This is part 1 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # # Run the following text with /bin/sh to create: # Makefile # README # README.1st # clharc.cs # clharc.def # dir.h # dir_dos.c # dir_os2.c # lharc.c # lharc.doc # lhdir.c # lhdir.h # lhio.c # lhio.h # lzhuf.c # mktemp.c # pipes.c # if test -r s2_seq_.tmp then echo "Must unpack archives in sequence!" next=`cat s2_seq_.tmp`; echo "Please unpack part $next next" exit 1; fi echo "x - extracting Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > Makefile && X# Makefile for LHArc UNIX X# Copyright(C) MCMLXXXIX Yooichi.Tagawa X# V0.01 Alpha Version 1989.05.28 Y.Tagawa X# V0.02 Alpha Version R2 1989.05.29 Y.Tagawa X# V0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa X X#----------------------------------------------------------------------- X# DIRECTORY ACCESS DEPENDENDS... X# The default (no need swtich) is your machine has X# opendir(),readdir(),closedir() library and 'direct' structure used. X# If your machine has no opendir (), readdir (), closedir () X# -DNONSYSTEM_DIR_LIBRARY X# and add lhdir.o into OBJS macro (see bellow) X# If your machine are 'dirent' (not 'direct') structure used, X# -DSYSV_SYSTEM_DIR X# Otherwise "Give up!" X# -DNODIRECTORY X# X#----------------------------------------------------------------------- X# MEMORY ACCESS STUFF X# Your machine has no BSTRING library (bcmp,bcopy,bzero). X# -DNOBSTRING X# X#----------------------------------------------------------------------- X# TIME STUFF X# Your include file '<sys/time.h>' has no 'struct tm', define this. X# -DSYSTIME_HAS_NO_TM X# If you are running on a BSD system, X# -DBSD X# X X# most of 4.[23]BSD X# - vax 4.[23]BSD, SONY NEWS 4.[23]BSD etc. X#SWITCHIES = X#OBJS = lharc.o lzhuf.o lhio.o X X# sample of System-V X# - NEC EWS4800 XSWITCHIES = -DSYSV_SYSTEM_DIR -DSYSTIME_HAS_NO_TM -DNOBSTRING XOBJS = lharc.o lzhuf.o lhio.o # lhdir.o X XCC = cc XCFLAGS = $(SWITCHIES) XLDFLAGS = -lx X X# Xlharc is test binary. Please rename to lharc at install. X# (see install target) Xall: xlharc X Xxlharc : $(OBJS) X $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) X X# For Debugging LzHuff module. Xlzhuf : lzhuf.c X $(CC) $(CFLAGS) -DSELFMAIN -o $* $*.c X Xlzhuf.o lhio.o : lhio.h X Xclean: X rm -f core lharc.o lzhuf.o lhdir.o lhio.o lharc.tar lharc.tar.Z X XF286 = -M2l Xlh286: $(OBJS) X @echo "Removing old object files" X rm *.o X $(MAKE) CFLAGS="$(F286) $(CFLAGS)" LDFLAGS="$(F286) $(LDFLAGS)" X mv xlharc lh286 X rm *.o SHAR_EOF chmod 0666 Makefile || echo "restore of Makefile fails" echo "x - extracting README (Text)" sed 's/^X//' << 'SHAR_EOF' > README && X -*- Text -*- X XLHarc UNIX V0.03 Release #3 Beta Version X X This is FREEWARE. But it's BETA-VERSION. X X Please reply to me. X X Sorry, lharc.doc file are written in JAPANESE (Shift-JIS KANJI) X X Thank you. X X Yooichi.Tagawa X Nikkei-MIX ID: y.tagawa X------------------------------------------------------------------------ X XHOW TO USE: X lharc {axevludmcp}[qnft] archive_file [files or directories...] X XCOMMAND: X KEY MEANS Like as (UNIX ar command) X --- ------------------------------ ------------------------------ X a Append to archive. ar r AFILE files... X x,e EXtract from archive. ar x AFILE [files...] X v,l View/List archive contents. ar t AFILE [files...] X u append newer files to archive. ar ru AFILE files... X d Delete from archive. ar d AFILE files... X m Move to archive. ar m AFILE files... X c re-construct new archive file. rm AFILE; ar r AFILE files... X p Print to STANDARD-OUTPUT ar p AFILE [files...] X X XOPTIONS: X q quiet X n no execute (debugging option) X f force (over write at extract) X t text-mode (this is provisional option) X X------------------------------------------------------------------------------ SHAR_EOF chmod 0666 README || echo "restore of README fails" echo "x - extracting README.1st (Text)" sed 's/^X//' << 'SHAR_EOF' > README.1st && X Partial Revision History X XApr 16, 1990 - Bill Davidsen (davidsen@crdos1.crd.ge.com) X X I got this source mailed to me and found that it didn't work on all Xthe machines I use here. I modified it so it runs on Xenix, Sun3, Sun4, Xand Ultrix. Since there's a perfectly good DOS version I haven't even Xtried it there. X X Note: I compiled with the native vendor compiler in all cases, Xavoiding fancy vectorizing, concurrent, or copylefted compilers. X X Changed the option for output to sysout to be p, to match zoo and arc, Xso I don't keep typing the wrong thing. SHAR_EOF chmod 0644 README.1st || echo "restore of README.1st fails" echo "x - extracting clharc.cs (Text)" sed 's/^X//' << 'SHAR_EOF' > clharc.cs && X(-W1 lharc.c lhio.c dir_os2.c mktemp.c pipes.c) X(-W1 -Ox lzhuf.c) Xsetargv.obj Xclharc.def Xclharc.exe X-as -lb -s0x2000 SHAR_EOF chmod 0666 clharc.cs || echo "restore of clharc.cs fails" echo "x - extracting clharc.def (Text)" sed 's/^X//' << 'SHAR_EOF' > clharc.def && XNAME CLHARC WINDOWCOMPAT XDESCRIPTION 'C-LHarc 1.00 - for MS-DOS and OS/2' SHAR_EOF chmod 0666 clharc.def || echo "restore of clharc.def fails" echo "x - extracting dir.h (Text)" sed 's/^X//' << 'SHAR_EOF' > dir.h && X/* X * @(#) dir.h 1.4 87/11/06 Public Domain. X * X * A public domain implementation of BSD directory routines for X * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield), X * August 1897 X * Ported to OS/2 by Kai Uwe Rommel and added scandir prototype X * December 1989 X */ X X#define rewinddir(dirp) seekdir(dirp, 0L) X X#define MAXNAMLEN 12 X Xstruct direct X{ X ino_t d_ino; /* a bit of a farce */ X int d_reclen; /* more farce */ X int d_namlen; /* length of d_name */ X char d_name[MAXNAMLEN + 1]; /* garentee null termination */ X}; X Xstruct _dircontents X{ X char *_d_entry; X struct _dircontents *_d_next; X}; X Xtypedef struct _dirdesc X{ X int dd_id; /* uniquely identify each open directory */ X long dd_loc; /* where we are in directory entry is this */ X struct _dircontents *dd_contents; /* pointer to contents of dir */ X struct _dircontents *dd_cp; /* pointer to current position */ X} DIR; X Xextern DIR *opendir(char *); Xextern struct direct *readdir(DIR *); Xextern void seekdir(DIR *, long); Xextern long telldir(DIR *); Xextern void closedir(DIR *); X Xextern int scandir(char *, struct direct ***, X int (*)(struct direct *), int (*)()); SHAR_EOF chmod 0666 dir.h || echo "restore of dir.h fails" echo "x - extracting dir_dos.c (Text)" sed 's/^X//' << 'SHAR_EOF' > dir_dos.c && X/* X * @(#)dir.c 1.4 87/11/06 Public Domain. X * X * A public domain implementation of BSD directory routines for X * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield), X * August 1897 X * Modified to use modern MS C library functions by Kai Uwe Rommel X * December 1989 X */ X X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/dir.h> X#include <malloc.h> X#include <string.h> X X#include <dos.h> X X#ifndef NULL X# define NULL 0 X#endif /* NULL */ X X#ifndef MAXPATHLEN X# define MAXPATHLEN 255 X#endif /* MAXPATHLEN */ X X/* attribute stuff */ X#define A_RONLY 0x01 X#define A_HIDDEN 0x02 X#define A_SYSTEM 0x04 X#define A_LABEL 0x08 X#define A_DIR 0x10 X#define A_ARCHIVE 0x20 X X X#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL) X X#define ATTRIBUTES (A_DIR) X/* #define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM) */ X/* #define ATTRIBUTES (A_RONLY | A_SYSTEM | A_DIR) */ X Xstatic char *getdirent(char *); Xstatic void free_dircontents(struct _dircontents *); X Xstatic struct find_t find; X X XDIR * Xopendir(name) X char *name; X{ X struct stat statb; X DIR *dirp; X char c; X char *s; X struct _dircontents *dp; X char nbuf[MAXPATHLEN + 1]; X X if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR) X return (DIR *) NULL; X if (Newisnull(dirp, DIR)) X return (DIR *) NULL; X if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/') X (void) strcat(strcpy(nbuf, name), "\\*.*"); X else X (void) strcat(strcpy(nbuf, name), "*.*"); X dirp->dd_loc = 0; X dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL; X X if ((s = getdirent(nbuf)) == (char *) NULL) X return dirp; X do { X if (Newisnull(dp, struct _dircontents) || (dp->_d_entry = X malloc((unsigned) (strlen(s) + 1))) == (char *) NULL) X { X if (dp) X free((char *) dp); X free_dircontents(dirp->dd_contents); X return (DIR *) NULL; X } X if (dirp->dd_contents) X dirp->dd_cp = dirp->dd_cp->_d_next = dp; X else X dirp->dd_contents = dirp->dd_cp = dp; X (void) strcpy(dp->_d_entry, s); X dp->_d_next = (struct _dircontents *) NULL; X } while ((s = getdirent((char *) NULL)) != (char *) NULL); X X dirp->dd_cp = dirp->dd_contents; X X return dirp; X} X Xvoid Xclosedir(dirp) X DIR *dirp; X{ X free_dircontents(dirp->dd_contents); X free((char *) dirp); X} X Xstruct direct * Xreaddir(dirp) X DIR *dirp; X{ X static struct direct dp; X X if (dirp->dd_cp == (struct _dircontents *) NULL) X return (struct direct *) NULL; X dp.d_namlen = dp.d_reclen = X strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry)); X strlwr(dp.d_name); /* JF */ X dp.d_ino = 0; X dirp->dd_cp = dirp->dd_cp->_d_next; X dirp->dd_loc++; X X return &dp; X} X Xvoid Xseekdir(dirp, off) X DIR *dirp; X long off; X{ X long i = off; X struct _dircontents *dp; X X if (off < 0) X return; X for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next) X ; X dirp->dd_loc = off - (i + 1); X dirp->dd_cp = dp; X} X Xlong Xtelldir(dirp) X DIR *dirp; X{ X return dirp->dd_loc; X} X Xstatic void Xfree_dircontents(dp) X struct _dircontents *dp; X{ X struct _dircontents *odp; X X while (dp) { X if (dp->_d_entry) X free(dp->_d_entry); X dp = (odp = dp)->_d_next; X free((char *) odp); X } X} X Xstatic char *getdirent(dir) Xchar *dir; X{ X int done; X X if (dir != (char *) NULL) X done = _dos_findfirst(dir, ATTRIBUTES, &find); X else /* get next entry */ X done = _dos_findnext(&find); X X if (done==0) X return find.name; X else X return (char *) NULL; X} X X Xsetfilemode(char *name, unsigned attr) X{ X _dos_setfileattr(name, attr); X} X Xgetfilemode(char *name, unsigned *attr) X{ X _dos_getfileattr(name, attr); X} SHAR_EOF chmod 0666 dir_dos.c || echo "restore of dir_dos.c fails" echo "x - extracting dir_os2.c (Text)" sed 's/^X//' << 'SHAR_EOF' > dir_os2.c && X/* X * @(#)dir.c 1.4 87/11/06 Public Domain. X * X * A public domain implementation of BSD directory routines for X * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield), X * August 1897 X * Ported to OS/2 by Kai Uwe Rommel X * December 1989 X */ X X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/dir.h> X#include <malloc.h> X#include <string.h> X X#define INCL_NOPM X#include <os2.h> X X#ifndef NULL X# define NULL 0 X#endif /* NULL */ X X#ifndef MAXPATHLEN X# define MAXPATHLEN 255 X#endif /* MAXPATHLEN */ X X/* attribute stuff */ X#define A_RONLY 0x01 X#define A_HIDDEN 0x02 X#define A_SYSTEM 0x04 X#define A_LABEL 0x08 X#define A_DIR 0x10 X#define A_ARCHIVE 0x20 X X X#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL) X X#define ATTRIBUTES (A_DIR) X/* #define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM) */ X/* #define ATTRIBUTES (A_RONLY | A_SYSTEM | A_DIR) */ X Xstatic char *getdirent(char *); Xstatic void free_dircontents(struct _dircontents *); X Xstatic HDIR hdir; Xstatic USHORT count; Xstatic FILEFINDBUF find; X X XDIR * Xopendir(name) X char *name; X{ X struct stat statb; X DIR *dirp; X char c; X char *s; X struct _dircontents *dp; X char nbuf[MAXPATHLEN + 1]; X X if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR) X return (DIR *) NULL; X if (Newisnull(dirp, DIR)) X return (DIR *) NULL; X if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/') X (void) strcat(strcpy(nbuf, name), "\\*.*"); X else X (void) strcat(strcpy(nbuf, name), "*.*"); X dirp->dd_loc = 0; X dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL; X X if ((s = getdirent(nbuf)) == (char *) NULL) X return dirp; X do { X if (Newisnull(dp, struct _dircontents) || (dp->_d_entry = X malloc((unsigned) (strlen(s) + 1))) == (char *) NULL) X { X if (dp) X free((char *) dp); X free_dircontents(dirp->dd_contents); X return (DIR *) NULL; X } X if (dirp->dd_contents) X dirp->dd_cp = dirp->dd_cp->_d_next = dp; X else X dirp->dd_contents = dirp->dd_cp = dp; X (void) strcpy(dp->_d_entry, s); X dp->_d_next = (struct _dircontents *) NULL; X } while ((s = getdirent((char *) NULL)) != (char *) NULL); X X dirp->dd_cp = dirp->dd_contents; X X return dirp; X} X Xvoid Xclosedir(dirp) X DIR *dirp; X{ X free_dircontents(dirp->dd_contents); X free((char *) dirp); X} X Xstruct direct * Xreaddir(dirp) X DIR *dirp; X{ X static struct direct dp; X X if (dirp->dd_cp == (struct _dircontents *) NULL) X return (struct direct *) NULL; X dp.d_namlen = dp.d_reclen = X strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry)); X strlwr(dp.d_name); /* JF */ X dp.d_ino = 0; X dirp->dd_cp = dirp->dd_cp->_d_next; X dirp->dd_loc++; X X return &dp; X} X Xvoid Xseekdir(dirp, off) X DIR *dirp; X long off; X{ X long i = off; X struct _dircontents *dp; X X if (off < 0) X return; X for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next) X ; X dirp->dd_loc = off - (i + 1); X dirp->dd_cp = dp; X} X Xlong Xtelldir(dirp) X DIR *dirp; X{ X return dirp->dd_loc; X} X Xstatic void Xfree_dircontents(dp) X struct _dircontents *dp; X{ X struct _dircontents *odp; X X while (dp) { X if (dp->_d_entry) X free(dp->_d_entry); X dp = (odp = dp)->_d_next; X free((char *) odp); X } X} X Xstatic char *getdirent(dir) Xchar *dir; X{ X int done; X X if (dir != (char *) NULL) X { /* get first entry */ X hdir = HDIR_CREATE; X count = 1; X done = DosFindFirst(dir, &hdir, ATTRIBUTES, X &find, sizeof(find), &count, 0L); X } X else /* get next entry */ X done = DosFindNext(hdir, &find, sizeof(find), &count); X X if (done==0) X return find.achName; X else X { X DosFindClose(hdir); X return (char *) NULL; X } X} X X Xsetfilemode(char *name, unsigned attr) X{ X DosSetFileMode(name, attr, 0L); X} X Xgetfilemode(char *name, unsigned *attr) X{ X DosQFileMode(name, (PUSHORT) attr, 0L); X} SHAR_EOF chmod 0666 dir_os2.c || echo "restore of dir_os2.c fails" echo "x - extracting lharc.c (Text)" sed 's/^X//' << 'SHAR_EOF' > lharc.c && X/*----------------------------------------------------------------------*/ X/* LHarc Archiver Driver for UNIX */ X/* */ X/* Copyright(C) MCMLXXXIX Yooichi.Tagawa */ X/* Thanks to H.Yoshizaki. (MS-DOS LHarc) */ X/* */ X/* V0.00 Original 1988.05.23 Y.Tagawa */ X/* V0.01 Alpha Version (for 4.2BSD) 1989.05.28 Y.Tagawa */ X/* V0.02 Alpha Version Rel.2 1989.05.29 Y.Tagawa */ X/* V0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa */ X/* V0.03a Fix few bug 1989.07.03 Y.Tagawa */ X/* V0.04 A lot of bugs fixed, strict mode 1990.01.13 Kai Uwe Rommel */ X/* V1.00 f and t commands, v option added 1990.01.27 Kai Uwe Rommel */ X/*----------------------------------------------------------------------*/ X X X#include <stdio.h> X#include <ctype.h> X#include <signal.h> X#include <sys/types.h> X#include <sys/stat.h> X X#ifdef PROF X#include <profile.h> X#endif X X#ifdef M_XENIX X#include <sys/fcntl.h> X#define ftruncate chsize X#endif X X#define STRICT X#define FASTCOPY X X#ifdef MSDOS X#include <fcntl.h> Xextern unsigned char _osmode; Xextern FILE *popen(); Xextern pclose(); X#define ftruncate chsize X#define mktemp Mktemp X#define SYSTIME_HAS_NO_TM X#define NOBSTRING X#define SYSNAME (_osmode ? "OS/2" : "MS-DOS") X#define OUR_EXTEND (_osmode ? EXTEND_OS2 : EXTEND_MSDOS) X#define FILENAME_LENGTH 128 X#define NULLFILE "nul" X#define TMP_FILENAME_TEMPLATE "lhXXXXXX" X#define NOT_COMPATIBLE_MODE X#define RMODE "rb" X#define WMODE "wb" X#else X#include <sys/file.h> X#include <sys/time.h> X#define SYSNAME "UNIX" X#define OUR_EXTEND EXTEND_UNIX X#define FILENAME_LENGTH 1024 X#define NULLFILE "/dev/null" X#define RMODE "r" X#define WMODE "w" X#endif X X#ifdef SYSTIME_HAS_NO_TM X/* most of System V, define SYSTIME_HAS_NO_TM */ X#include <time.h> X#endif X X/* #include <strings.h> */ X#include <string.h> X X X/*----------------------------------------------------------------------*/ X/* DIRECTORY ACCESS STUFF */ X/*----------------------------------------------------------------------*/ X#ifndef NODIRECTORY X#ifdef SYSV_SYSTEM_DIR X X#include <dirent.h> X#define DIRENTRY struct dirent X#define NAMLEN(p) strlen (p->d_name) X X#else /* not SYSV_SYSTEM_DIR */ X X#ifdef NONSYSTEM_DIR_LIBRARY X#include "lhdir.h" X#else /* not NONSYSTEM_DIR_LIBRARY */ X#include <sys/dir.h> X#endif /* not NONSYSTEM_DIR_LIBRARY */ X X#define DIRENTRY struct direct X#define NAMLEN(p) p->d_namlen X Xextern DIR *opendir (); Xextern struct direct *readdir (); X X#endif /* not SYSV_SYSTEM_DIR */ X#endif X X/*----------------------------------------------------------------------*/ X/* FILE ATTRIBUTES */ X/*----------------------------------------------------------------------*/ X X/* If file mode is not compatible between your Machine/OS and X LHarc standard UNIX file mode. X (See UNIX Manual stat(1), <sys/stat.h>, X and/or below UNIX_* difinitions. ) */ X/* #define NOT_COMPATIBLE_MODE */ X X X/*----------------------------------------------------------------------*/ X/* MEMORY FUNCTIONS */ X/*----------------------------------------------------------------------*/ X X#ifdef NOBSTRING X#ifdef __ANSI__ X#include "mem.h" X#define bcmp(a,b,n) memcmp ((a),(b),(n)) X#define bcopy(s,d,n) memmove((d),(s),(n)) X#define bzero(d,n) memset((d),0,(n)) X#else /* not __ANSI__ */ X#include "memory.h" X#define bcmp(a,b,n) memcmp ((a),(b),(n)) X#define bcopy(s,d,n) memcpy ((d),(s),(n)) /* movmem((s),(d),(n)) */ X#define bzero(d,n) memset((d),0,(n)) X#endif /* not __ANSI__ */ X#endif /* NOBSTRING */ X X X/*----------------------------------------------------------------------*/ X/* YOUR CUSTOMIZIES */ X/*----------------------------------------------------------------------*/ X/* These difinitions are changable to you like. */ X/* #define ARCHIVENAME_EXTENTION ".LZH" */ X/* #define TMP_FILENAME_TEMPLATE "/tmp/lhXXXXXX" */ X/* #define BACKUPNAME_EXTENTION ".BAK" */ X/* #define MULTIBYTE_CHAR */ X X X X#define SJC_FIRST_P(c) \ X (((unsigned char)(c) >= 0x80) && \ X (((unsigned char)(c) < 0xa0) || \ X ((unsigned char)(c) >= 0xe0) && \ X ((unsigned char)(c) < 0xfd))) X#define SJC_SECOND_P(c) \ X (((unsigned char)(c) >= 0x40) && \ X ((unsigned char)(c) < 0xfd) && \ X ((ungigned char)(c) != 0x7f)) X X#ifdef MULTIBYTE_CHAR X#define MULTIBYTE_FIRST_P SJC_FIRST_P X#define MULTIBYTE_SECOND_P SJC_SECOND_P X#endif X X/*----------------------------------------------------------------------*/ X/* OTHER DIFINITIONS */ X/*----------------------------------------------------------------------*/ X X#ifndef SEEK_SET X#define SEEK_SET 0 X#define SEEK_CUR 1 X#define SEEK_END 2 X#endif X X X/* non-integral functions */ Xextern struct tm *localtime (); Xextern char *getenv (); Xextern char *malloc (); Xextern char *realloc (); X Xextern int rson[]; X X/* external variables */ Xextern int errno; X X X#define FALSE 0 X#define TRUE 1 Xtypedef int boolean; X X X/*----------------------------------------------------------------------*/ X/* LHarc FILE DIFINITIONS */ X/*----------------------------------------------------------------------*/ X#define METHOD_TYPE_STRAGE 5 X#define LZHUFF0_METHOD "-lh0-" X#define LZHUFF1_METHOD "-lh1-" X#define LARC4_METHOD "-lz4-" X#define LARC5_METHOD "-lz5-" X X#define I_HEADER_SIZE 0 X#define I_HEADER_CHECKSUM 1 X#define I_METHOD 2 X#define I_PACKED_SIZE 7 X#define I_ORIGINAL_SIZE 11 X#define I_LAST_MODIFIED_STAMP 15 X#define I_ATTRIBUTE 19 X#define I_NAME_LENGTH 21 X#define I_NAME 22 X X#define I_CRC 22 /* + name_length */ X#define I_EXTEND_TYPE 24 /* + name_length */ X#define I_MINOR_VERSION 25 /* + name_length */ X#define I_UNIX_LAST_MODIFIED_STAMP 26 /* + name_length */ X#define I_UNIX_MODE 30 /* + name_length */ X#define I_UNIX_UID 32 /* + name_length */ X#define I_UNIX_GID 34 /* + name_length */ X#define I_UNIX_EXTEND_BOTTOM 36 /* + name_length */ X X X X#define EXTEND_GENERIC 0 X#define EXTEND_UNIX 'U' X#define EXTEND_MSDOS 'M' X#define EXTEND_MACOS 'm' X#define EXTEND_OS9 '9' X#define EXTEND_OS2 '2' X#define EXTEND_OS68K 'K' X#define EXTEND_OS386 '3' X#define EXTEND_HUMAN 'H' X#define EXTEND_CPM 'C' X#define EXTEND_FLEX 'F' X X#define GENERIC_ATTRIBUTE 0x20 X#define GENERIC_DIRECTORY_ATTRIBUTE 0x10 X X#define CURRENT_UNIX_MINOR_VERSION 0x00 X X X Xtypedef struct LzHeader { X unsigned char header_size; X char method[METHOD_TYPE_STRAGE]; X long packed_size; X long original_size; X long last_modified_stamp; X unsigned short attribute; X char name[256]; X unsigned short crc; X boolean has_crc; X unsigned char extend_type; X unsigned char minor_version; X /* extend_type == EXTEND_UNIX and convert from other type. */ X time_t unix_last_modified_stamp; X unsigned short unix_mode; X unsigned short unix_uid; X unsigned short unix_gid; X} LzHeader; X X#define UNIX_FILE_TYPEMASK 0170000 X#define UNIX_FILE_REGULAR 0100000 X#define UNIX_FILE_DIRECTORY 0040000 X#define UNIX_SETUID 0004000 X#define UNIX_SETGID 0002000 X#define UNIX_STYCKYBIT 0001000 X#define UNIX_OWNER_READ_PERM 0000400 X#define UNIX_OWNER_WRITE_PERM 0000200 X#define UNIX_OWNER_EXEC_PERM 0000100 X#define UNIX_GROUP_READ_PERM 0000040 X#define UNIX_GROUP_WRITE_PERM 0000020 X#define UNIX_GROUP_EXEC_PERM 0000010 X#define UNIX_OTHER_READ_PERM 0000004 X#define UNIX_OTHER_WRITE_PERM 0000002 X#define UNIX_OTHER_EXEC_PERM 0000001 X#define UNIX_RW_RW_RW 0000666 X X#define LZHEADER_STRAGE 256 X X/*----------------------------------------------------------------------*/ X/* PROGRAM */ X/*----------------------------------------------------------------------*/ X X X#define CMD_UNKNOWN 0 X#define CMD_EXTRACT 1 X#define CMD_APPEND 2 X#define CMD_VIEW 3 X Xint cmd = CMD_UNKNOWN; Xchar **cmd_filev; Xint cmd_filec; Xchar *archive_name; X Xchar expanded_archive_name[FILENAME_LENGTH]; Xchar temporary_name[FILENAME_LENGTH]; Xchar pager[FILENAME_LENGTH]; X X X/* options */ Xboolean quiet = FALSE; Xboolean text_mode = FALSE; X/*boolean verbose = FALSE; */ X#ifdef MSDOS Xboolean keepcase = FALSE; /* all filenames single case */ X#else /* UNIX */ Xboolean keepcase = TRUE; /* don't mess with case of filenames */ X#endif /* set case options */ Xboolean noexec = FALSE; /* debugging option */ Xboolean force = FALSE; Xboolean prof = FALSE; X X X/* view flags */ Xboolean long_format_listing = FALSE; X X/* extract flags */ Xboolean output_to_test = FALSE; Xboolean output_to_stdout = FALSE; X X/* append flags */ Xboolean new_archive = FALSE; Xboolean update_if_newer = FALSE; Xboolean update_freshen = FALSE; Xboolean delete_after_append = FALSE; Xboolean delete_from_archive = FALSE; X Xboolean remove_temporary_at_error = FALSE; X X X/*----------------------------------------------------------------------*/ X/* NOTES : Text File Format */ X/* GENERATOR NewLine */ X/* [generic] 0D 0A */ X/* [MS-DOS] 0D 0A */ X/* [MacOS] 0D */ X/* [UNIX] 0A */ X/*----------------------------------------------------------------------*/ X Xchar *myname; X X Xvoid userbreak() X{ X error("Interrupt."); X} X X Xmain (argc, argv) X int argc; X char *argv[]; X{ X char *p; X X myname = argv[0]; X signal(SIGINT, userbreak); X X#ifdef PROF X PROFINIT(PT_USER|PT_USEKP, NULL); X PROFCLEAR(PT_USER); X PROFON(PT_USER); X#endif X X if (argc < 3) X print_tiny_usage_and_exit (); X X /* commands */ X#ifdef MSDOS X switch (tolower(argv[1][0])) X#else X switch (argv[1][0]) X#endif X { X case 'x': X case 'e': X cmd = CMD_EXTRACT; X break; X X case 't': X output_to_test = TRUE; X cmd = CMD_EXTRACT; X break; X X case 'p': X output_to_stdout = TRUE; X cmd = CMD_EXTRACT; X break; X X case 'c': X new_archive = TRUE; X cmd = CMD_APPEND; X break; X X case 'a': X cmd = CMD_APPEND; X break; X X case 'd': X delete_from_archive = TRUE; X cmd = CMD_APPEND; X break; X X case 'u': X update_if_newer = TRUE; X cmd = CMD_APPEND; X break; X X case 'f': X update_if_newer = update_freshen = TRUE; X cmd = CMD_APPEND; X break; X X case 'm': X delete_after_append = TRUE; X cmd = CMD_APPEND; X break; X X case 'v': X long_format_listing = TRUE; X cmd = CMD_VIEW; X break; X X case 'l': X cmd = CMD_VIEW; X break; X X case 'h': X default: X print_tiny_usage_and_exit (); X } X X /* options */ X p = &argv[1][1]; X for (p = &argv[1][1]; *p; p++) X { X#ifdef MSDOS X switch (tolower(*p)) X#else X switch (*p) X#endif X { X case 'q': quiet = TRUE; break; X case 'f': force = TRUE; break; X/* case 'p': prof = TRUE; break; */ X/* case 'v': verbose = TRUE; break; */ X case 'p': if (p[1] != 0) { X strcpy(pager, p + 1); X *(p + 1) = 0; X } X else strcpy(pager, "more"); X break; X case 't': text_mode = TRUE; break; X case 'n': noexec = TRUE; break; X X default: X fprintf (stderr, "unknown option '%c'.\n", *p); X exit (1); X } X } X X /* archive file name */ X archive_name = argv[2]; X X /* target file name */ X cmd_filec = argc - 3; X cmd_filev = argv + 3; X sort_files (); X X switch (cmd) X { X case CMD_EXTRACT: cmd_extract (); break; X case CMD_APPEND: cmd_append (); break; X case CMD_VIEW: cmd_view (); break; X } X X#ifdef PROF X PROFOFF(PT_USER); X PROFDUMP(PT_USER, "profile.out"); X PROFFREE(PT_USER); X#endif X X exit (0); X} X Xprint_tiny_usage_and_exit () X{ X printf("\nC-LHarc for %s Version 1.00 (C) 1989-1990 Y.Tagawa, Kai Uwe Rommel\n%s", X "\nUsage: %s {axevlufdmctp}[qnftv] archive_file [files or directories...]\n", X SYSNAME, myname); X printf("\nCommands: Options:\n%s%s%s%s%s%s%s%s%s%s", X " a Append q quiet\n", X " x,e EXtract n no execute\n", X " v,l View/List f force (over write at extract)\n", X " u Update t files are TEXT files\n", X " f Freshen p<pager> use file pager for p command\n", X " d Delete\n", X " m Move\n", X " c re-Construct new archive\n", X " t Test archive\n", X " p Print to STDOUT\n"); X exit (1); X} X Xmessage (title, msg) X char *title, *msg; X{ X fprintf (stderr, "%s ", myname); X if (errno == 0) X fprintf (stderr, "%s %s\n", title, msg); X else X perror (msg); X} X Xwarning (msg) X char *msg; X{ X message ("Warning:", msg); X} X Xerror (msg) X char *msg; X{ X message ("Error:", msg); X X if (remove_temporary_at_error) X { X#ifdef MSDOS X fcloseall(); X#endif X unlink (temporary_name); X } X X exit (1); X} X Xchar *writting_filename; Xchar *reading_filename; X Xwrite_error () X{ X error (writting_filename); X} X Xread_error () X{ X error (reading_filename); X} X X X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X Xboolean expand_archive_name (dst, src) X char *dst, *src; X{ X register char *p, *dot; X X strcpy (dst, src); X X for (p = dst, dot = (char*)0; *p; p++) X if (*p == '.') X dot = p; X else if (*p == '/' || *p == '\\') X dot = (char*)0; X X if (dot) X p = dot; X X#ifdef ARCHIVENAME_EXTENTION X strcpy (p, ARCHIVENAME_EXTENTION); X#else X strcpy (p, ".lzh"); X#endif X return (strcmp (dst, src) != 0); X} X X#ifdef MSDOS X#define STRING_COMPARE(a,b) stricmp((a),(b)) X#else X#define STRING_COMPARE(a,b) strcmp((a),(b)) X#endif X Xint sort_by_ascii (a, b) X char **a, **b; X{ X return STRING_COMPARE (*a, *b); X} X Xsort_files () X{ X qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii); X} X X#ifndef MSDOS Xchar *strdup (string) X char *string; X{ X int len = strlen (string) + 1; X char *p = malloc (len); X bcopy (string, p, len); X return p; X} X#endif X X#ifdef NODIRECTORY X/* please need your imprementation */ Xboolean find_files (name, v_filec, v_filev) X char *name; X int *v_filec; X char ***v_filev; X{ X return FALSE; /* DUMMY */ X} X#else Xboolean find_files (name, v_filec, v_filev) X char *name; X int *v_filec; X char ***v_filev; X{ X char newname[FILENAME_LENGTH]; X int len, n; X DIR *dirp; X DIRENTRY *dp; X int alloc_size = 64; /* any (^_^) */ X char **filev; X int filec = 0; X X if ( strcmp(name, ".") == 0 ) X newname[0] = 0; X else X strcpy (newname, name); X X len = strlen (newname); X dirp = opendir (name); X X if (dirp) X { X filev = (char**)malloc (alloc_size * sizeof(char *)); X if (!filev) X error ("not enough memory"); X X for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp)) X { X n = NAMLEN (dp); X if ( X#ifndef MSDOS X (dp->d_ino != 0) && X#endif X ((dp->d_name[0] != '.') || X ((n != 1) && X ((dp->d_name[1] != '.') || X (n != 2)))) && /* exclude '.' and '..' */ X (strcmp (dp->d_name, temporary_name) != 0) && X (strcmp (dp->d_name, archive_name) != 0)) X { X if ((len != 0) && (newname[len-1] != '/') && (newname[len-1] != '\\')) X { X#ifdef MSDOS X newname[len] = '\\'; X#else X newname[len] = '/'; X#endif X strncpy (newname+len+1, dp->d_name, n); X newname[len+n+1] = '\0'; X } X else X { X strncpy (newname+len, dp->d_name, n); X newname[len+n] = '\0'; X } X X filev[filec++] = strdup (newname); X if (filec == alloc_size) X { X alloc_size += 64; X filev = (char**)realloc (filev, alloc_size * sizeof(char *)); X } X } X } X closedir (dirp); X } X X *v_filev = filev; X *v_filec = filec; X if (dirp) X { X qsort (filev, filec, sizeof (char*), sort_by_ascii); X return TRUE; X } X else X return FALSE; X} X#endif X Xfree_files (filec, filev) X int filec; X char **filev; X{ X int i; X X for (i = 0; i < filec; i ++) X free (filev[i]); X X free (filev); X} X X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X Xint calc_sum (p, len) X register char *p; X register int len; X{ X register int sum; X X for (sum = 0; len; len--) X sum += *p++; X X return sum & 0xff; X} X Xunsigned char *get_ptr; X#define setup_get(PTR) get_ptr = (unsigned char*)(PTR) X#define get_byte() (*get_ptr++) X#define put_ptr get_ptr X#define setup_put(PTR) put_ptr = (unsigned char*)(PTR) X#define put_byte(c) *put_ptr++ = (unsigned char)(c) X Xunsigned short get_word () X{ X int b0, b1; X X b0 = get_byte (); X b1 = get_byte (); X return (b1 << 8) + b0; X} X Xput_word (v) X unsigned int v; X{ X put_byte (v); X put_byte (v >> 8); X} X Xlong get_longword () X{ X long 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} X Xput_longword (v) X long v; X{ X put_byte (v); X put_byte (v >> 8); X put_byte (v >> 16); X put_byte (v >> 24); X} X X Xmsdos_to_unix_filename (name, len) X register char *name; X register int len; X{ X register int i; X X#ifdef MULTIBYTE_CHAR X for (i = 0; i < len; i ++) X { X if (MULTIBYTE_FIRST_P (name[i]) && X MULTIBYTE_SECOND_P (name[i+1])) X i ++; X#ifndef MSDOS X else if (name[i] == '\\') X name[i] = '/'; X#endif X else if (isupper (name[i])) X name[i] = tolower (name[i]); X } X#else X for (i = 0; i < len; i ++) X { X#ifndef MSDOS X if (name[i] == '\\') X name[i] = '/'; X else X#endif X if (isupper (name[i])) X name[i] = tolower (name[i]); X } X#endif X} X Xgeneric_to_unix_filename (name, len) X register char *name; X register int len; X{ X register int i; X boolean lower_case_used = keepcase; X X#ifdef MULTIBYTE_CHAR X for (i = 0; i < len; i ++) X { X if (MULTIBYTE_FIRST_P (name[i]) && X MULTIBYTE_SECOND_P (name[i+1])) X i ++; X else if (islower (name[i])) X { X lower_case_used = TRUE; X break; X } X } X for (i = 0; i < len; i ++) X { X if (MULTIBYTE_FIRST_P (name[i]) && X MULTIBYTE_SECOND_P (name[i+1])) X i ++; X#ifndef MSDOS X else if (name[i] == '\\') X name[i] = '/'; X#endif X else if (!lower_case_used && isupper (name[i])) X name[i] = tolower (name[i]); X } X#else X for (i = 0; i < len; i ++) X if (islower (name[i])) X { X lower_case_used = TRUE; X break; X } X for (i = 0; i < len; i ++) X { X#ifndef MSDOS X if (name[i] == '\\') X name[i] = '/'; X else X#endif X if (!lower_case_used && isupper (name[i])) X name[i] = tolower (name[i]); X } X#endif X} X Xmacos_to_unix_filename (name, len) X register char *name; X register int len; X{ X register int i; X X for (i = 0; i < len; i ++) X { X if (name[i] == ':') X name[i] = '/'; X else if (name[i] == '/') X name[i] = ':'; X } X} X X/*----------------------------------------------------------------------*/ X/* */ X/* Generic stamp format: */ X/* */ X/* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */ X/* |<-------- year ------->|<- month ->|<-- day -->| */ X/* */ X/* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */ X/* |<--- hour --->|<---- minute --->|<- second*2 ->| */ X/* */ X/*----------------------------------------------------------------------*/ X X Xlong gettz () X{ X#if MSDOS X return timezone; X#else X#ifdef BSD X struct timeval tp; X struct timezone tzp; X gettimeofday (&tp, &tzp); /* specific to 4.3BSD */ X/* return (tzp.tz_minuteswest * 60 + (tzp.tz_dsttime != 0 ? 60L * 60L : 0));*/ X return (tzp.tz_minuteswest * 60); X#else /* SYSV */ X struct tm timep; X long dummytime; X X time(&dummytime); X timep = *localtime(&dummytime); X return timep.tm_tzadj; X#endif X#endif X} X X#ifdef NOT_USED Xstruct tm *msdos_to_unix_stamp_tm (a) X long a; X{ X static struct tm t; X t.tm_sec = ( a & 0x1f) * 2; X t.tm_min = (a >> 5) & 0x3f; X t.tm_hour = (a >> 11) & 0x1f; X t.tm_mday = (a >> 16) & 0x1f; X t.tm_mon = (a >> 16+5) & 0x0f - 1; X t.tm_year = ((a >> 16+9) & 0x7f) + 80; X return &t; X} X#endif X Xtime_t generic_to_unix_stamp (t) X long t; X{ X struct tm tm; X long longtime; X static unsigned int dsboy[12] = X { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; X unsigned long days; X X tm.tm_year = ((int)(t >> 25) & 0x7f) + 80; X tm.tm_mon = ((int)(t >> 21) & 0x0f) - 1; /* 0..11 means Jan..Dec */ X tm.tm_mday = (int)(t >> 16) & 0x1f; /* 1..31 means 1st,...31st */ X X tm.tm_hour = ((int)t >> 11) & 0x1f; X tm.tm_min = ((int)t >> 5) & 0x3f; X tm.tm_sec = ((int)t & 0x1f) * 2; X X#ifdef MSDOS X longtime = mktime(&tm); X#else X /* Calculate days since 1970.01.01 */ X days = (365 * (tm.tm_year - 70) + /* days due to whole years */ X (tm.tm_year - 70 + 1) / 4 + /* days due to leap years */ X dsboy[tm.tm_mon] + /* days since beginning of this year */ X tm.tm_mday-1); /* days since beginning of month */ X X if ((tm.tm_year % 4 == 0) && X (tm.tm_year % 400 != 0) && X (tm.tm_mon >= 2)) /* if this is a leap year and month */ X days++; /* is March or later, add a day */ X X /* Knowing the days, we can find seconds */ X longtime = (((days * 24) + tm.tm_hour) * 60 + tm.tm_min) * 60 + tm.tm_sec; X longtime += gettz (); /* adjust for timezone */ X#endif X X /* special case: if MSDOS format date and time were zero, then we set X time to be zero here too. */ X if (t == 0) X longtime = 0; X X /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00. */ X return (time_t)longtime; X} X Xlong unix_to_generic_stamp (t) X time_t t; X{ X struct tm *tm = localtime (&t); X unsigned long stamp; X X stamp = ( ((long)(tm->tm_year - 80)) << 25 ); X stamp += ( ((long)(tm->tm_mon + 1)) << 21 ); X stamp += ( ((long)(tm->tm_mday)) << 16 ); X stamp += ( ((long)(tm->tm_hour)) << 11 ); X stamp += ( ((long)(tm->tm_min)) << 5 ); X stamp += ( ((long)(tm->tm_sec)) >> 1 ); X X return stamp; X} X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X Xboolean get_header (fp, hdr) X FILE *fp; X register LzHeader *hdr; X{ X int header_size; X int name_length; X char data[LZHEADER_STRAGE]; X int checksum; X int i; X X bzero ((char *)hdr, sizeof (LzHeader)); X X if (((header_size = getc (fp)) == EOF) || (header_size == 0)) X { X return FALSE; /* finish */ X } X X if (fread (data + I_HEADER_CHECKSUM, X sizeof (char), header_size + 1, fp) < header_size + 1) X { X error ("Invalid header (LHarc file ?)\a"); X return FALSE; /* finish */ X } X X setup_get (data + I_HEADER_CHECKSUM); X checksum = calc_sum (data + I_METHOD, header_size); X if (get_byte () != checksum) X warning ("Checksum error (LHarc file?)\a"); X X hdr->header_size = header_size; X bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE); X#ifdef OLD X if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) && X (bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) && X (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) && X (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0)) X { X warning ("Unknown method (LHarc file ?)"); X return FALSE; /* invalid method */ X } X#endif X setup_get (data + I_PACKED_SIZE); X hdr->packed_size = get_longword (); X hdr->original_size = get_longword (); X hdr->last_modified_stamp = get_longword (); X hdr->attribute = get_word (); X name_length = get_byte (); X for (i = 0; i < name_length; i ++) X hdr->name[i] =(char)get_byte (); X hdr->name[name_length] = '\0'; X X /* defaults for other type */ X hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW; X hdr->unix_gid = 0; X hdr->unix_uid = 0; X X if (header_size - name_length >= 24) X { /* EXTEND FORMAT */ X hdr->crc = get_word (); X hdr->extend_type = get_byte (); X hdr->minor_version = get_byte (); X hdr->has_crc = TRUE; X } X else if (header_size - name_length == 22) X { /* Generic with CRC */ X hdr->crc = get_word (); X hdr->extend_type = EXTEND_GENERIC; X hdr->has_crc = TRUE; X } X else if (header_size - name_length == 20) X { /* Generic no CRC */ X hdr->extend_type = EXTEND_GENERIC; X hdr->has_crc = FALSE; X } X else X { X warning ("Unknown header (LHarc file ?)"); X return FALSE; X } X X switch (hdr->extend_type) X { X case EXTEND_MSDOS: X msdos_to_unix_filename (hdr->name, name_length); X hdr->unix_last_modified_stamp = X generic_to_unix_stamp (hdr->last_modified_stamp); X break; X X case EXTEND_UNIX: X hdr->unix_last_modified_stamp = (time_t)get_longword (); X hdr->unix_mode = get_word (); X hdr->unix_uid = get_word (); X hdr->unix_gid = get_word (); X break; X X case EXTEND_MACOS: X macos_to_unix_filename (hdr->name, name_length); X hdr->unix_last_modified_stamp = X generic_to_unix_stamp (hdr->last_modified_stamp); X break; X X default: X generic_to_unix_filename (hdr->name, name_length); X hdr->unix_last_modified_stamp = X generic_to_unix_stamp (hdr->last_modified_stamp); X } X X return TRUE; X} X Xinit_header (name, v_stat, hdr) X char *name; X struct stat *v_stat; X LzHeader *hdr; X{ X bcopy (LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE); X hdr->packed_size = 0; X hdr->original_size = v_stat->st_size; X hdr->last_modified_stamp = unix_to_generic_stamp (v_stat->st_mtime); X#ifdef MSDOS X getfilemode(name, &(hdr->attribute)); X#else X hdr->attribute = GENERIC_ATTRIBUTE; X#endif X strcpy (hdr->name, name); X hdr->crc = 0x0000; X hdr->extend_type = OUR_EXTEND; X hdr->unix_last_modified_stamp = v_stat->st_mtime; X /* 00:00:00 since JAN.1.1970 */ X#ifdef NOT_COMPATIBLE_MODE X hdr->unix_mode = v_stat->st_mode; X#else X hdr->unix_mode = v_stat->st_mode; X#endif X X hdr->unix_uid = v_stat->st_uid; X hdr->unix_gid = v_stat->st_gid; X X if ((v_stat->st_mode & S_IFMT) == S_IFDIR) X { X bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE); X hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE; X hdr->original_size = 0; X strcat (hdr->name, "/"); X } X} X X/* Write only unix extended header. */ Xwrite_header (nafp, hdr) X FILE *nafp; X LzHeader *hdr; X{ X int header_size; X int name_length; X char data[LZHEADER_STRAGE], *ptr; X int cnt; X X bzero (data, LZHEADER_STRAGE); X bcopy (hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE); X setup_put (data + I_PACKED_SIZE); X put_longword (hdr->packed_size); X put_longword (hdr->original_size); X put_longword (hdr->last_modified_stamp); X put_word (hdr->attribute); X X#ifdef STRICT X X if ( hdr->name[1] == ':' ) X { X name_length = strlen(hdr->name + 2); X put_byte (name_length); X bcopy (hdr->name + 2, data + I_NAME, name_length); X } X else X { X name_length = strlen(hdr->name); X put_byte (name_length); X bcopy (hdr->name, data + I_NAME, name_length); X } X X for ( ptr = data + I_NAME, cnt = 0; cnt < name_length; ptr++, cnt++ ) X { X/* *ptr = toupper(*ptr); */ X X if ( *ptr == '/' ) X *ptr = '\\'; X } X#else X name_length = strlen (hdr->name); X put_byte (name_length); X bcopy (hdr->name, data + I_NAME, name_length); X#endif X X setup_put (data + I_NAME + name_length); X put_word (hdr->crc); X#ifdef STRICT X header_size = I_EXTEND_TYPE - 2 + name_length; X#else X put_byte (OUR_EXTEND); X put_byte (CURRENT_UNIX_MINOR_VERSION); X put_longword ((long)hdr->unix_last_modified_stamp); X put_word (hdr->unix_mode); X put_word (hdr->unix_uid); X put_word (hdr->unix_gid); X header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length; X#endif X data[I_HEADER_SIZE] = header_size; X data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size); X X if (fwrite (data, sizeof (char), header_size + 2, nafp) == 0) X error ("cannot write to temporary file"); X} X Xboolean archive_is_msdos_sfx1 (name) X char *name; X{ X int len = strlen (name); X return ((len >= 4) && X (strcmp (name + len - 4, ".com") == 0 || X strcmp (name + len - 4, ".exe") == 0)); X} X Xboolean skip_msdos_sfx1_code (fp) X FILE *fp; X{ X unsigned char buffer[2048]; X unsigned char *p, *q; X int n; X X n = fread (buffer, sizeof (char), 2048, fp); X X for (p = buffer + 2, q = buffer + n - 5; p < q; p ++) X { X /* found "-l??-" keyword (as METHOD type string) */ X if (p[0] == '-' && p[1] == 'l' && p[4] == '-') X { X /* size and checksum validate check */ X if (p[-2] > 20 && p[-1] == calc_sum (p, p[-2])) X { X fseek (fp, (long) ((p - 2) - buffer) - n, SEEK_CUR); X return TRUE; X } X } X } X X fseek (fp, (long) -n, SEEK_CUR); X return FALSE; X} X X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X Xmake_tmp_name (original, name) X char *original; X char *name; X{ X#ifdef TMP_FILENAME_TEMPLATE X /* "/tmp/lhXXXXXX" etc. */ X strcpy (name, TMP_FILENAME_TEMPLATE); X#else X char *p, *s; X X strcpy (name, original); X for (p = name, s = (char*)0; *p; p++) X if (*p == '/' || *p == '\\') X s = p; X X strcpy ((s ? s+1 : name), "lhXXXXXX"); X#endif X X mktemp (name); X} X Xmake_backup_name (name, orginal) X char *name; X char *orginal; X{ X register char *p, *dot; X X strcpy (name, orginal); X for (p = name, dot = (char*)0; *p; p ++) X { X if (*p == '.') X dot = p; X else if (*p == '/' || *p == '\\') X dot = (char*)0; X } X X if (dot) X p = dot; X X#ifdef BACKUPNAME_EXTENTION X strcpy (p, BACKUPNAME_EXTENTION) X#else X strcpy (p, ".bak"); X#endif X} X Xmake_standard_archive_name (name, orginal) X char *name; X char *orginal; X{ X register char *p, *dot; X X strcpy (name, orginal); X for (p = name, dot = (char*)0; *p; p ++) X { X if (*p == '.') X dot = p; X else if (*p == '/' || *p == '\\') X dot = (char*)0; X } X X if (dot) X p = dot; X X#ifdef ARCHIVENAME_EXTENTION X strcpy (p, ARCHIVENAME_EXTENTION); X#else X strcpy (p, ".lzh"); X#endif X} X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X X Xboolean need_file (name) X char *name; X{ X int i; X X if (cmd_filec == 0) X return TRUE; X X for (i = 0; i < cmd_filec; i ++) X { X if (STRING_COMPARE (cmd_filev[i], name) == 0) X return TRUE; X } X X return FALSE; X} X XFILE *xfopen (name, mode) X char *name, *mode; X{ X FILE *fp; X X if ((fp = fopen (name, mode)) == NULL) X error (name); X X return fp; X} X X X/*----------------------------------------------------------------------*/ X/* Listing Stuff */ X/*----------------------------------------------------------------------*/ X X/* need 14 or 22 (when long_format_listing is TRUE) column spaces */ Xprint_size (packed_size, original_size) X long packed_size, original_size; X{ X if (long_format_listing) X printf ("%7ld ", packed_size); X X printf ("%7ld ", original_size); X X if (original_size == 0L) X printf ("******"); X else X printf ("%3d.%1d%%", X (int)((packed_size * 100L) / original_size), X (int)((packed_size * 1000L) / original_size) % 10); X} X X/* need 12 or 17 (when long_format_listing is TRUE) column spaces */ Xprint_stamp (t) X time_t t; X{ X static boolean got_now = FALSE; X static time_t now; X static unsigned int threshold; X static char t_month[12*3+1] = "JanFebMarAprMayJunJulAugSepOctNovDec"; X struct tm *p; X X if (t == 0) X { X if (long_format_listing) X printf (" "); /* 17 spaces */ X else X printf (" "); /* 12 spaces */ X X return; X } X X if (!got_now) X { X time (&now); X p = localtime (&now); X threshold = p->tm_year * 12 + p->tm_mon - 6; X got_now = TRUE; X } X X p = localtime (&t); X X if (long_format_listing) X printf ("%.3s %2d %02d:%02d %04d", X &t_month[p->tm_mon * 3], p->tm_mday, X p->tm_hour, p->tm_min, p->tm_year + 1900); X else X if (p->tm_year * 12 + p->tm_mon > threshold) X printf ("%.3s %2d %02d:%02d", X &t_month[p->tm_mon * 3], p->tm_mday, p->tm_hour, p->tm_min); X else X printf ("%.3s %2d %04d", X &t_month[p->tm_mon * 3], p->tm_mday, p->tm_year + 1900); X} X Xprint_bar () X{ X /* 17+1+(0 or 7+1)+7+1+6+1+(0 or 1+4)+(12 or 17)+1+20 */ X /* 12345678901234567_ 1234567_123456 _123456789012 1234 */ X if (long_format_listing) X#ifdef STRICT X printf ("------- ------- ------ ---- ----------------- -------------\n"); X#else X printf ("----------------- ------- ------- ------ ---- ----------------- -------------\n"); X#endif X else X#ifdef STRICT X printf ("------- ------ ------------ --------------------\n"); X#else X printf ("----------------- ------- ------ ------------ --------------------\n"); X#endif X} X X X/* X view X */ Xcmd_view () X{ X FILE *fp; X LzHeader hdr; X register char *p; X long a_packed_size = 0L; X long a_original_size = 0L; X int n_files = 0; X struct stat v_stat; X X if ((fp = fopen (archive_name, RMODE)) == NULL) X if (!expand_archive_name (expanded_archive_name, archive_name)) X error (archive_name); X else X { X errno = 0; X fp = xfopen (expanded_archive_name, RMODE); X archive_name = expanded_archive_name; X } X X if (archive_is_msdos_sfx1 (archive_name)) X { X skip_msdos_sfx1_code (fp); X } X X if (!quiet) X { X /* 12345678901234567_ 1234567_123456 _ 123456789012 1234 */ X#ifdef STRICT X printf ("%s SIZE RATIO%s %s STAMP %s NAME\n", X#else X printf (" PERMSSN UID GID %s SIZE RATIO%s %s STAMP %s NAME\n", X#endif X long_format_listing ? " PACKED " : "", /* 8,0 */ X long_format_listing ? " CRC" : "", /* 5,0 */ X long_format_listing ? " " : "", /* 2,0 */ X long_format_listing ? " " : ""); /* 3,0 */ X print_bar (); X } X X while (get_header (fp, &hdr)) X { X if (need_file (hdr.name)) X { X if (hdr.extend_type == EXTEND_UNIX) X { X#ifndef STRICT X printf ("%c%c%c%c%c%c%c%c%c%4d/%-4d", X ((hdr.unix_mode & UNIX_OWNER_READ_PERM) ? 'r' : '-'), X ((hdr.unix_mode & UNIX_OWNER_WRITE_PERM) ? 'w' : '-'), X ((hdr.unix_mode & UNIX_OWNER_EXEC_PERM) ? 'x' : '-'), X ((hdr.unix_mode & UNIX_GROUP_READ_PERM) ? 'r' : '-'), X ((hdr.unix_mode & UNIX_GROUP_WRITE_PERM) ? 'w' : '-'), X ((hdr.unix_mode & UNIX_GROUP_EXEC_PERM) ? 'x' : '-'), X ((hdr.unix_mode & UNIX_OTHER_READ_PERM) ? 'r' : '-'), X ((hdr.unix_mode & UNIX_OTHER_WRITE_PERM) ? 'w' : '-'), X ((hdr.unix_mode & UNIX_OTHER_EXEC_PERM) ? 'x' : '-'), X hdr.unix_uid, hdr.unix_gid); X#endif X } X else X { X switch (hdr.extend_type) X { /* max 18 characters */ X case EXTEND_GENERIC: p = "[Generic]"; break; X X case EXTEND_CPM: p = "[CP/M]"; break; X X /* OS-9 and FLEX's CPU is MC-6809. I like it. :-) */ X case EXTEND_FLEX: p = "[FLEX]"; break; X X case EXTEND_OS9: p = "[OS-9]"; break; X X /* I guessed from this ID. Is this right? */ X case EXTEND_OS68K: p = "[OS-9/68K]"; break; X X case EXTEND_MSDOS: p = "[MS-DOS]"; break; X X /* I have Macintosh. :-) */ X case EXTEND_MACOS: p = "[Mac OS]"; break; X X case EXTEND_OS2: p = "[OS/2]"; break; X X case EXTEND_HUMAN: p = "[Human68K]"; break; X X case EXTEND_OS386: p = "[OS-386]"; break; X X#ifdef EXTEND_TOWNSOS X /* This ID isn't fixed */ X case EXTEND_TOWNSOS: p = "[TownsOS]"; break; X#endif X X /* Ouch! Please customize it's ID. */ X default: p = "[Unknown]"; break; X } X#ifndef STRICT X printf ("%-18.18s", p); X#endif X } X X print_size (hdr.packed_size, hdr.original_size); X X if (long_format_listing) X if (hdr.has_crc) X printf (" %04x", hdr.crc); X else X printf (" ****"); X X printf (" "); X print_stamp (hdr.unix_last_modified_stamp); X printf (" %s\n", hdr.name); X n_files ++; X a_packed_size += hdr.packed_size; X a_original_size += hdr.original_size; X } X fseek (fp, hdr.packed_size, SEEK_CUR); X } X X fclose (fp); X if (!quiet) X { X print_bar (); X X#ifndef STRICT X printf (" Total %4d file%c ", X n_files, (n_files == 1) ? ' ' : 's'); X#endif X print_size (a_packed_size, a_original_size); X printf (" "); X X if (long_format_listing) X printf (" "); X X if (stat (archive_name, &v_stat) < 0) X print_stamp ((time_t)0); X else X print_stamp (v_stat.st_mtime); X X#ifdef STRICT X printf (" %4d file%c ", X n_files, (n_files == 1) ? ' ' : 's'); X#endif X printf ("\n"); X } X X return; X} X X Xboolean make_parent_path (name) X char *name; X{ X char path[FILENAME_LENGTH]; X struct stat v_stat; X register char *p; X X /* make parent directory name into PATH for recursive call */ X strcpy (path, name); X for (p = path + strlen (path); p > path; p --) X if (p[-1] == '/' || p[-1] == '\\') X { X p[-1] = '\0'; X break; X } X X if (p == path) X return FALSE; /* no more parent. */ X X if (stat (path, &v_stat) >= 0) X { X if ((v_stat.st_mode & S_IFMT) != S_IFDIR) X return FALSE; /* already exist. but it isn't directory. */ X return TRUE; /* already exist its directory. */ X } X X errno = 0; X X if (!quiet) X message ("Making Directory", path); X X if (mkdir (path, 0777) >= 0) /* try */ X return TRUE; /* successful done. */ X X errno = 0; X X if (!make_parent_path (path)) X return FALSE; X X if (mkdir (path, 0777) < 0) /* try again */ X return FALSE; X X return TRUE; X} X XFILE *open_with_make_path (name) X char *name; X{ X FILE *fp; X struct stat v_stat; X char buffer[1024]; X X if (stat (name, &v_stat) >= 0) X { X if ((v_stat.st_mode & S_IFMT) != S_IFREG) X return NULL; X X if (!force) X { X for (;;) X { X fprintf (stderr, "%s OverWrite ?(Yes/No/All) ", name); X fflush (stderr); X gets (buffer); X if (buffer[0] == 'N' || buffer[0] == 'n') X return NULL; X if (buffer[0] == 'Y' || buffer[0] == 'y') X break; X if (buffer[0] == 'A' || buffer[0] == 'a') X { X force = TRUE; X break; X } X } X } X } X X fp = fopen (name, WMODE); X if (!fp) X { X errno = 0; X if (!make_parent_path (name)) X return NULL; X X fp = fopen (name, WMODE); X if (!fp) X message ("Error:", name); X } X return fp; X} X X#ifdef MSDOS Xvoid dosname(char *name) X{ X char *ptr, *first = NULL, *last = NULL; X char temp[8]; X X for ( ptr = strchr(name, 0); ptr >= name; ptr-- ) X if ( *ptr == '.' ) X { X if ( last == NULL ) X last = ptr; X } X else if ( (*ptr == '/') || (*ptr == '\\') ) X { X first = ptr + 1; X break; X } X X if ( first == NULL ) X first = name; X if ( last == NULL ) X last = strchr(name, 0); X X for ( ptr = first; ptr < last; ptr++ ) X if ( *ptr == '.' ) X *ptr = '_'; X X if ( strlen(last) > 4 ) X last[4] = 0; X X if ( last - first > 8 ) X { X strcpy(temp, last); X strcpy(first + 8, last); X } X} X#endif X Xextern int decode_lzhuf (), decode_larc (); Xextern int decode_stored_crc (), decode_stored_nocrc (); X Xextract_one (fp, hdr) X FILE *fp; X LzHeader *hdr; X{ X FILE *ofp; /* output file */ X char name[1024]; X time_t utimebuf[2]; X int crc; X int (*decode_proc)(); /* (ifp,ofp,original_size,name) */ X int save_quiet; X X strcpy (name, hdr->name); X if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR) X { X if (bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) == 0) X decode_proc = decode_lzhuf; X else if ((bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) == 0) || X (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) == 0)) X decode_proc = (hdr->has_crc) ? decode_stored_crc : decode_stored_nocrc; X else if (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) == 0) X decode_proc = decode_larc; X else X message ("Error:", "Sorry, Cannot Extract this method."); X X reading_filename = archive_name; X writting_filename = name; X if (output_to_stdout) X { X if (!quiet) X printf ("::::::::\r\n%s\r\n::::::::\r\n", name); X X if ( strlen(pager) != 0 ) X ofp = popen(pager, WMODE); X else X ofp = stdout; X X save_quiet = quiet; X quiet = TRUE; X crc = (*decode_proc) (fp, ofp, hdr->original_size, name); X quiet = save_quiet; X X if ( strlen(pager) != 0 ) X pclose(ofp); X } X else if (output_to_test) X { X ofp = fopen(NULLFILE, WMODE); X crc = (*decode_proc) (fp, ofp, hdr->original_size, name); X fclose(ofp); X } X else X { X#ifdef MSDOS X dosname(name); X#endif X if ((ofp = open_with_make_path (name)) == NULL) X return; X else X { X crc = (*decode_proc) (fp, ofp, hdr->original_size, name); X fclose (ofp); X } X } X X if (hdr->has_crc && (crc != hdr->crc)) X if (output_to_test) X message ("Error:", "CRC failed\a"); X else X error ("CRC failed\a"); X } X else X { X /* NAME has trailing SLASH '/', (^_^) */ X if (!output_to_stdout && X !make_parent_path (name)) X error (name); X } X X if (!output_to_stdout && !output_to_test) X { X utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp; X utime (name, utimebuf); X X#ifdef NOT_COMPATIBLE_MODE X setfilemode(name, hdr->attribute); X#else X chmod (name, hdr->unix_mode); X#endif X X#ifndef MSDOS X chown (name, hdr->unix_uid, hdr->unix_gid); X#endif X errno = 0; X } X} X X X/* X extract X */ Xcmd_extract () X{ X LzHeader hdr; X long pos; X FILE *fp; X X if ((fp = fopen (archive_name, RMODE)) == NULL) X if (!expand_archive_name (expanded_archive_name, archive_name)) X error (archive_name); X else X { X errno = 0; X fp = xfopen (expanded_archive_name, RMODE); X archive_name = expanded_archive_name; X } X X if (archive_is_msdos_sfx1 (archive_name)) X { X skip_msdos_sfx1_code (fp); X } X X while (get_header (fp, &hdr)) X { X if (need_file (hdr.name)) X { X pos = ftell (fp); X extract_one (fp, &hdr); X fseek (fp, pos + hdr.packed_size, SEEK_SET); SHAR_EOF echo "End of part 1" echo "File lharc.c is continued in part 2" echo "2" > s2_seq_.tmp exit 0 -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) VMS is a text-only adventure game. If you win you can use unix.
davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (12/06/90)
#!/bin/sh # this is part 2 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file lharc.c continued # CurArch=2 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file lharc.c" sed 's/^X//' << 'SHAR_EOF' >> lharc.c X } else { X fseek (fp, hdr.packed_size, SEEK_CUR); X } X } X X fclose (fp); X X return; X} X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X Xextern int encode_lzhuf (); Xextern int encode_storerd_crc (); X Xappend_one (fp, nafp, hdr) X FILE *fp, *nafp; X LzHeader *hdr; X{ X long header_pos, next_pos, org_pos, data_pos; X long v_original_size, v_packed_size; X X reading_filename = hdr->name; X writting_filename = temporary_name; X X org_pos = ftell (fp); X header_pos = ftell (nafp); X write_header (nafp, hdr); /* DUMMY */ X X if (hdr->original_size == 0) X { X printf("%s - not frozen\n",hdr->name); X return; /* previous write_header is not DUMMY. (^_^) */ X } X X data_pos = ftell (nafp); X hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size, X &v_original_size, &v_packed_size, hdr->name); X if (v_packed_size < v_original_size) X { X next_pos = ftell (nafp); X } X else X { /* retry by stored method */ X fseek (fp, org_pos, SEEK_SET); X fseek (nafp, data_pos, SEEK_SET); X hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size, X &v_original_size, &v_packed_size); X fflush (nafp); X next_pos = ftell (nafp); X ftruncate (fileno (nafp), next_pos); X bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE); X } X hdr->original_size = v_original_size; X hdr->packed_size = v_packed_size; X fseek (nafp, header_pos, SEEK_SET); X write_header (nafp, hdr); X fseek (nafp, next_pos, SEEK_SET); X} X Xwrite_tail (nafp) X FILE *nafp; X{ X putc (0x00, nafp); X} X Xcopy_old_one (oafp, nafp, hdr) X FILE *oafp, *nafp; X LzHeader *hdr; X{ X if (noexec) X { X fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR); X } X else X { X reading_filename = archive_name; X writting_filename = temporary_name; X copy_file (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size); X } X} X X XFILE *append_it (name, oafp, nafp) X char *name; X FILE *oafp, *nafp; X{ X LzHeader ahdr, hdr; X FILE *fp; X long old_header; X int cmp; X int filec; X char **filev; X int i; X X struct stat v_stat; X boolean directory; X X /* check that any added name is not the same as the archive name */ X if (strcmp(name, archive_name) == 0) return oafp; X X if (!delete_from_archive) X if (stat (name, &v_stat) < 0) X { X message ("Error:", name); X return oafp; X } X X directory = ((v_stat.st_mode & S_IFMT) == S_IFDIR); X X init_header (name, &v_stat, &hdr); X X if (!delete_from_archive && !directory && !noexec) X fp = xfopen (name, RMODE); X X while (oafp) X { X old_header = ftell (oafp); X if (!get_header (oafp, &ahdr)) X { X fclose (oafp); X oafp = NULL; X break; X } X else X { X cmp = STRING_COMPARE (ahdr.name, hdr.name); X if (cmp < 0) X { /* SKIP */ X fseek (oafp, old_header, SEEK_SET); X copy_old_one (oafp, nafp, &ahdr); X } X else if (cmp == 0) X { /* REPLACE */ X fseek (oafp, ahdr.packed_size, SEEK_CUR); X break; X } X else /* cmp > 0, INSERT */ X { X fseek (oafp, old_header, SEEK_SET); X break; X } X } X } X X if (delete_from_archive) X { X if (noexec) X fprintf (stderr, "DELETE %s\n", name); X else X printf ("%s - Deleted\n", name); X } X else X { X if ( !oafp || (cmp > 0) || !update_if_newer X || (ahdr.unix_last_modified_stamp < hdr.unix_last_modified_stamp) ) X { X if (noexec) X fprintf (stderr, "APPEND %s\n", name); X else X#ifdef STRICT X if ( !directory ) X#endif X if ( !update_freshen || (cmp == 0) ) X append_one (fp, nafp, &hdr); X } X else X { /* archive has old one */ X fseek (oafp, old_header, SEEK_SET); X copy_old_one (oafp, nafp, &ahdr); X } X X if (!directory) X { X if (!noexec) X fclose (fp); X } X else X { /* recurcive call */ X if (find_files (name, &filec, &filev)) X { X for (i = 0; i < filec; i ++) X oafp = append_it (filev[i], oafp, nafp); X free_files (filec, filev); X } X return oafp; X } X } X X return oafp; X} X X Xremove_it (name) X char *name; X{ X struct stat v_stat; X int i; X char **filev; X int filec; X X if (stat (name, &v_stat) < 0) X { X fprintf (stderr, "Cannot access \"%s\".\n", name); X return; X } X X if ((v_stat.st_mode & S_IFMT) == S_IFDIR) X { X if (!find_files (name, &filec, &filev)) X { X fprintf (stderr, "Cannot open directory \"%s\".\n", name); X return; X } X X for (i = 0; i < filec; i ++) X remove_it (filev[i]); X X free_files (filec, filev); X X if (noexec) X printf ("REMOVE DIR %s\n", name); X else if (rmdir (name) < 0) X fprintf (stderr, "Cannot remove directory \"%s\".\n", name); X else if (!quiet) X printf ("%s - Removed\n", name); X } X else X { X if (noexec) X printf ("REMOVE %s\n", name); X else if (unlink (name) < 0) X fprintf (stderr, "Cannot delete \"%s\".\n", name); X else if (!quiet) X printf ("%s - Removed\n", name); X } X} X X#ifdef FASTCOPY X#define BUFFER_SIZE 16384 X X#ifndef O_BINARY X#define O_BINARY 0 X#endif X Xcopy_archive(src, dst) Xchar *src; Xchar *dst; X{ X int ih, oh; X unsigned chunk; X char *buffer = (char *) rson; X X printf ("Copying temp to archive ... "); X X ih = open (src, O_RDONLY | O_BINARY); X if ( ih == -1 ) X error(src); X oh = open (dst, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); X if ( oh == -1 ) X error(dst); X X while ( (chunk = read(ih, buffer, BUFFER_SIZE)) > 0 ) X if ( write(oh, buffer, chunk) != chunk ) X error(dst); X X close (ih); X close (oh); X X printf("\b\b\b\b \b\b\b\b.\n"); X} X#endif X Xcmd_append () X{ X LzHeader ahdr; X FILE *oafp, *nafp; X char backup_archive_name [ FILENAME_LENGTH ]; X char new_archive_name_buffer [ FILENAME_LENGTH ]; X char *new_archive_name; X int i; X long old_header; X struct stat v_stat; X boolean old_archive_exist; X X if (cmd_filec == 0) X return; X X make_tmp_name (archive_name, temporary_name); X X if ((oafp = fopen (archive_name, RMODE)) == NULL) X if (expand_archive_name (expanded_archive_name, archive_name)) X { X errno = 0; X oafp = fopen (expanded_archive_name, RMODE); X archive_name = expanded_archive_name; X } X X old_archive_exist = (oafp) ? TRUE : FALSE; X if (new_archive && oafp) X { X fclose (oafp); X oafp = NULL; X } X X if (oafp && archive_is_msdos_sfx1 (archive_name)) X { X skip_msdos_sfx1_code (oafp); X make_standard_archive_name (new_archive_name_buffer, archive_name); X new_archive_name = new_archive_name_buffer; X } X else X { X new_archive_name = archive_name; X } X X errno = 0; X if (!noexec) X { X nafp = xfopen (temporary_name, WMODE); X remove_temporary_at_error = TRUE; X } X X for (i = 0; i < cmd_filec; i ++) X oafp = append_it (cmd_filev[i], oafp, nafp); X X if (oafp) X { X old_header = ftell (oafp); X while (get_header (oafp, &ahdr)) X { X fseek (oafp, old_header, SEEK_SET); X copy_old_one (oafp, nafp, &ahdr); X old_header = ftell (oafp); X } X fclose (oafp); X } X X if (!noexec) X { X write_tail (nafp); X fclose (nafp); X } X X make_backup_name (backup_archive_name, archive_name); X X if (!noexec && old_archive_exist) X { X unlink(backup_archive_name); X X if (rename (archive_name, backup_archive_name) < 0) X error (archive_name); X } X X if (!quiet && new_archive_name == new_archive_name_buffer) X { /* warning at old archive is SFX */ X printf ("New Archive File is \"%s\"\n", new_archive_name); X } X X if (!noexec && rename (temporary_name, new_archive_name) < 0) X { X if (stat (temporary_name, &v_stat) < 0) X error (temporary_name); X X#ifdef FASTCOPY X copy_archive(temporary_name, archive_name); X#else X oafp = xfopen (temporary_name, RMODE); X nafp = xfopen (archive_name, WMODE); X reading_filename = temporary_name; X writting_filename = archive_name; X copy_file (oafp, nafp, (long)v_stat.st_size); X fclose (nafp); X fclose (oafp); X#endif X X unlink (temporary_name); X } X remove_temporary_at_error = FALSE; X X if (delete_after_append) X { X if (!quiet && !noexec) X printf ("Erasing...\n"); X for (i = 0; i < cmd_filec; i ++) X remove_it (cmd_filev[i]); X } X X return; X} X X/* XENIX kludges */ X#ifdef M_XENIX Xrename(old, new) Xchar *old, *new; X{ X char cmd[256]; X X sprintf(cmd, "/bin/mv %s %s", old, new); X system(cmd); X} X#endif /* XENIX */ SHAR_EOF echo "File lharc.c is complete" chmod 0666 lharc.c || echo "restore of lharc.c fails" echo "x - extracting lharc.doc (Text)" sed 's/^X//' << 'SHAR_EOF' > lharc.doc && X------------------------------------------------------------------------------ X LHarc UNIX Release #3 V0.03 beta version X Copyright (C) 1989 Yooichi.Tagawa X X cl mj X zoMIX ID: y.tagawa X------------------------------------------------------------------------------ X 1Lv X X UNIX EL LHarc p X X X H :AAIfgH"),hAUNIX E LHarc (LHarc UNIX) p LHarc F X *5\7B X X Xyg"{z X lharc {axevludmcp}[qnft] archive_file [files or directories...] X X R}hMAaxevludmcp L"Cj)PFBpwh5\7B(H*s B) X IvVM qnft )gp"-BE`wh B\E7B X (H* B\B3 X X XyA[JCut@C<z X wh5=t@C<Lt@C*H/jNA.lzh pt@C<LckIt X A5D5\7B5=*AD;Lj X AIKhM h\9q*A ^pcATtBbNXF5D .lzh Ij7 X iL*G")F]\5")Fv"\7B X .com (fQ .exe LTbtBNXLj X 3j= SFX ().W X 5\7B5)5ALHarc UNIX EMASFX `.Lt@Cp X ME+\9qBSFX `.LA[JCut@CIN5DG A/ X =j X X X XyR}hjz X a A[JCut@CIwh5=t@CpG A X fBNg X WD X x \=M e A[JCut@CL)gwh5=t@C)7WDLt@ X Cp X v \=M l A[JCut@C`I X WDLt@CLjp\&5\7Bl Lj X qpoM5\7B X u wh5=t@C*A[JCut@C`I X CfhV5")AA[JCut@C`I X jN X d A[JCut@CL)gwh5=t@Cp X m A[JCut@CIwh5=t@Cp X 5=t@Cp X c A[JCut@CL`epj X p X p A[JCut@CL)gwh5=t@C)7WDL`e X pW X XyIvVjz X q bZ[WL}'p X n @ X f X t eLXg[hBMS-DOS EELeLXgt@CL | X O X dl*Omi)`5j\9qB) X X Xy] X MS-DOS LHarc V1.13c ( i"MA;jHO) E X CF] X Z[W*oi)`5j\9qB X LHarc UNIX E X h* X X XyzzKhz X H :LpEA X X 1. X 2. zz`eIB"DMA X a. zzL X v X X gppS7i1FB X b. LHarc IN7it A ?l*t/gjD X jg`E+i>/ X t A ?l*t/gjD"i1Fp>&5=hLgppS X 7i1FB X c. oCi X 3. X 4. 1Lv X X5H"B X 5. X mH"B X 6. 1Lv X p5D`)\mH"B1Lj X H-ALHarc F<fADM"/H"B X 7. $pI X F_iB X a. 1Lv X b. $pL X =j X c. CXg[LhiF5Dgp7ij X $1Fp X \=A;LF+L9 X d. $ppt A ?lF5D X $pRMA;LT|[gp X X Xy X LZHUF @L X ;jp Nifty IP n5A\=ALArc L X 1jgLvv)g LZHUF @yQAMS-DOS E LHarc p X A X N X qI X X X XGL V0.03: X * 1. quiet F text_mode LIvVpt/D]\5=B X text_mode LIvVMAdl*Omi)`5j\9qLE X 5DgAD->3"B X 2. G [bZ[W*sKXH* i)`5j\9qB X + 3. X 1qH`qE""LE5e$)B(^_^) X + 4. TufBNg X A[JCut@CIG ALbhpFhL<-1F*E+\5=B X * 5. 3k/W X E7B LArc type 4 yQAtype 5 I`N 5\5=B X * 6. MS-DOS ELZtGNXg NgLA[JCu`.` p X $I5\5=B X 7. MS-DOS E V1.13c LA[JCut@C* [MS-DOS] EH-A X [generic] IHh\7*AMS-DOS ELLE =h(\*))gM X [MS-DOS] FF/E+itH[}bgIHAD"iFv"\7B(^_^) X 8. MS-DOS E V1.13c ELTufBNg X W X 9. {M VAX 11/785 UNIX 4.2BSD E X (`FbNRj* i)`5j\9q) X + 10. d66)Fv"\7*AMS-DOS <--> UNIX X L]MoCi X * 11. System-V VLZApeUI X * 12. v F l R}hL\&`TLO X * 13. lzhuf.c )g @mK6pMT+\5=B(Fv$) X XGL V0.02: X 1. verbose/quiet/text_mode option M\>"E7B X 2. G [bZ[W*sKXH* i)`5j\9qB X * 3. X 1qH`qE""LE5e$)B(^_^) X * 4. TufBNg X A[JCut@CIG ALbhpFhL<-1F*E+\5=B X 5. 3k/W X >Fv"\7B X 6. ; X 5D"\9qB X 7. MS-DOS E V1.13c LA[JCut@C* [MS-DOS] EH-A X [generic] IHh\7*AMS-DOS ELLE =h(\*))gM X [MS-DOS] FF/E+itH[}bgIHAD"iFv"\7B(^_^) X 8. MS-DOS E V1.13c ELTufBNg X W X 9. {M vax 11/785 UNIX 4.2BSD E X (`FbNRj* i)`5j\9q) X * 10. d66)Fv"\7*AMS-DOS <--> UNIX X L]MoCi X XGL V0.01: X 1. verbose/quiet/text_mode option M\>"E7B X 2. G [bZ[W*sKXH* i)`5j\9qB X 3. X 4. TufBNg X 5. 3k/W X >Fv"\7B X 6. ; X 5D"\9qB X 7. MS-DOS E V1.13c LA[JCut@C* [MS-DOS] EH-A X [generic] IHh\7*AMS-DOS ELLE =h(\*))gM X [MS-DOS] FF/E+itH[}bgIHAD"iFv"\7B(^_^) X 8. MS-DOS E V1.13c ELTufBNg X W X 9. {M vax 11/785 UNIX 4.2BSD E X (`FbNRj* i)`5j\9q) X X X------------------------------------------------------------------------------ SHAR_EOF chmod 0666 lharc.doc || echo "restore of lharc.doc fails" echo "x - extracting lhdir.c (Text)" sed 's/^X//' << 'SHAR_EOF' > lhdir.c && X/*----------------------------------------------------------------------*/ X/* Directory access routine for LHarc UNIX */ X/* */ X/* Copyright(C) MCMLXXXIX Yooichi.Tagawa */ X/* */ X/* Emulate opendir(),readdir(),closedir() function for LHarc */ X/* */ X/* V0.00 Original 1988.05.31 Y.Tagawa */ X/* V0.03 Release #3 for LHarc UNIX 1988.07.02 Y.Tagawa */ X/*----------------------------------------------------------------------*/ X X X#include <sys/types.h> X X/* Where is O_RDONLY ? (^_^) */ X#include <sys/file.h> X#ifndef O_RDONLY X#include <fcntl.h> X#endif X X#define direct old_direct X#include <sys/dir.h> X#undef direct X X#include "lhdir.h" X XDIR *opendir (name) X char *name; X{ X register DIR *dirp; X register int fd; X if ((fd = open (name, O_RDONLY)) >= 0) X { X if ((dirp = (DIR*)malloc (sizeof (DIR))) != (DIR*)0) X { X dirp->dd_fd = fd; X dirp->dd_loc = 0; X dirp->dd_size = 0; X return dirp; X } X X close (fd); X } X X return (DIR*)0; X} X Xstruct direct *readdir (dirp) X register DIR *dirp; X{ X static struct direct lhdir; X register struct old_direct *dp; X X do { X if (dirp->dd_loc >= dirp->dd_size) X { X dirp->dd_loc = 0; X if ((dirp->dd_size = read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0) X return (struct direct *)0; X } X X dp = (struct old_direct *)(dirp->dd_buf + dirp->dd_loc); X X if (dirp->dd_loc + sizeof (struct old_direct) > dirp->dd_size) X return (struct direct *)0; X X dirp->dd_loc += sizeof (struct old_direct); X X } while (dp->d_ino == 0) ; X X /* construct new format */ X lhdir.d_ino = dp->d_ino; X strncpy (lhdir.d_name, dp->d_name, DIRSIZ); X lhdir.d_name[DIRSIZ] = '\0'; X lhdir.d_namlen = strlen (lhdir.d_name); X X return &lhdir; X} X Xclosedir (dirp) X DIR *dirp; X{ X close (dirp->dd_fd); X free (dirp); X} X SHAR_EOF chmod 0600 lhdir.c || echo "restore of lhdir.c fails" echo "x - extracting lhdir.h (Text)" sed 's/^X//' << 'SHAR_EOF' > lhdir.h && X/*----------------------------------------------------------------------*/ X/* Directory access routine for LHarc UNIX */ X/* */ X/* Copyright(C) MCMLXXXIX Yooichi.Tagawa */ X/* Emulate opendir(),readdir(),closedir() function for LHarc */ X/* */ X/* V0.00 Original 1988.05.31 Y.Tagawa */ X/* V0.03 Release #3 for LHarc UNIX 1988.07.02 Y.Tagawa */ X/*----------------------------------------------------------------------*/ X X X/* DIRBLKSIZ must be sizeof (SYSTEM struct direct) * N !!! */ X X#ifndef DIRBLKSIZ X#define DIRBLKSIZ 512 X#endif X Xstruct direct { X int d_ino; X int d_namlen; X char d_name[256]; X}; X Xtypedef struct { X int dd_fd; X int dd_loc; X int dd_size; X char dd_buf[DIRBLKSIZ]; X} DIR; X X Xextern DIR *opendir (); Xextern struct direct *readdir (); Xextern closedir (); X SHAR_EOF chmod 0600 lhdir.h || echo "restore of lhdir.h fails" echo "x - extracting lhio.c (Text)" sed 's/^X//' << 'SHAR_EOF' > lhio.c && X/*----------------------------------------------------------------------*/ X/* File I/O module for LHarc UNIX */ X/* */ X/* Copyright(C) MCMLXXXIX Yooichi.Tagawa */ X/* */ X/* V0.00 Original 1989.06.25 Y.Tagawa */ X/* V0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa */ X/* V0.03a Fix few bugs 1989.07.04 Y.Tagawa */ X/*----------------------------------------------------------------------*/ X X#include <stdio.h> X#include "lhio.h" X X#ifndef BUFFER_SIZE X#define BUFFER_SIZE 16384 X#endif X X Xextern int text_mode; /* in lharc.c */ XFILE *crc_infile, *crc_outfile; /* in lzhuf.c */ X Xextern int rson[]; X X/* These functions are NO-RETURN */ Xextern read_error (); Xextern write_error (); X X Xint crc_getc_cashe; Xunsigned int crc_value; Xunsigned int crc_table[0x100]; Xlong crc_size; X X Xcrcsub (ptr, length) X char *ptr; X register int length; X{ X register unsigned char *p; X register unsigned int ctmp; X X if (length != 0) X { X ctmp = crc_value; X p = (unsigned char*)ptr; X for (; length; length --) X { X ctmp ^= (unsigned int)*p++; X ctmp = (ctmp >> 8) ^ crc_table [ ctmp & 0xff ]; X } X crc_value = ctmp; X } X} X X#ifndef __GNUC__ Xvoid putc_crc (c) X int c; X{ X CRC_CHAR (c); X if (!text_mode || (c != 0x0d && c != 0x1a)) X { X putc (c, crc_outfile); X } X} X Xint getc_crc () X{ X int c; X X if (crc_getc_cashe != EOF) X { X c = crc_getc_cashe; X crc_getc_cashe = EOF; X CRC_CHAR (c); X crc_size++; X } X else if ((c = getc (crc_infile)) != EOF) X { X if (text_mode && c == 0x0a) X { X crc_getc_cashe = c; X c = 0x0d; X } X CRC_CHAR (c); X crc_size++; X } X return c; X} X#endif X X X Xinit_crc () X{ X static int inited = 0; X register unsigned int *p = crc_table; X register int i, j; X register unsigned int x; X X if (!inited) { X for (j = 0; j < 256; j ++) { X x = j; X for (i = 0; i < 8; i ++) { X if ((x & 1) != 0) { X x = (x >> 1) ^ 0xa001; X } else { X x = (x >> 1); X } X } X *p ++ = x; X } X inited = 1; X } X crc_value = 0; X crc_getc_cashe = EOF; X crc_size = 0; X} X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X X/* if return value is -1, see errno */ Xcopy_binary_file (ifp, ofp, size, crc_flag) X FILE *ifp, *ofp; X long size; X int crc_flag; /* as boolean value */ X{ X char *buffer = (char *) rson; X int read_size; X int n; X X /* safty */ X fflush (ofp); X X while (size > 0) X { X read_size = ((size < (long)BUFFER_SIZE) ? (int)size : BUFFER_SIZE); X X n = fread (buffer, sizeof (char), read_size, ifp); X X if (n == 0) X read_error (); X X if (fwrite (buffer, sizeof (char), n, ofp) < n) X write_error (); X X if (crc_flag) X crcsub (buffer, n); X X size -= (long)n; X } X} X X/* read UNIX text file '0A' and write generic text file '0D0A' */ Xwrite_generic_text_file (ifp, ofp, size) X FILE *ifp, *ofp; X long size; X{ X char buffer[BUFFER_SIZE]; X int read_size, write_count, n, m; X register char *p, *p1, *e; X X /* safty */ X fflush (ofp); X X write_count = 0; X X while (size > 0) X { X read_size = ((size < BUFFER_SIZE) ? (int)size : BUFFER_SIZE); X X n = fread (buffer, sizeof (char), read_size, ifp); X X if (n == 0) X read_error (); X X for (p1 = p = buffer, e = buffer + n; p < e; p++) X { X if (*p == '\n') X { X if ((m = p - p1) != 0) X { X if (fwrite (p1, sizeof (char), m, ofp) < m) X write_error (); X crcsub (p1, m); X } X putc (0x0d, ofp); X if (feof (ofp)) X write_error (); X CRC_CHAR (0x0d); X p1 = p; X write_count ++; X } X } X if ((m = p - p1) != 0) X { X if (fwrite (p1, sizeof (char), m, ofp) < m) X write_error (); X crcsub (p1, m); X } X X write_count += (long)n; X size -= (long)n; X } X X crc_size = write_count; X} X X/* read generic text file '0D0A' and write UNIX text file '0A' */ Xread_generic_text_file (ifp, ofp, size, crc_flag) X FILE *ifp, *ofp; X long size; X int crc_flag; X{ X char buffer[BUFFER_SIZE]; X int read_size, write_size, n, m; X register char *p, *p1, *e; X X /* safty */ X fflush (ofp); X X while (size > 0) X { X read_size = ((size < BUFFER_SIZE) ? (int)size : BUFFER_SIZE); X X n = fread (buffer, sizeof (char), read_size, ifp); X X if (n == 0) X read_error (); X X crcsub (buffer, n); X X for (p1 = p = buffer, e = buffer + n; p < e; p ++) X { X if (*p == 0x0d) X { X if ((m = p - p1) != 0) X { X if (fwrite (p1, sizeof (char), m, ofp) < m) X write_error (); X } X p1 = p+1; X } X } X if ((m = p - p1) != 0) X { X if (fwrite (p1, sizeof (char), m, ofp) < m) X write_error (); X } X X size -= (long)n; X } X} X X X/*----------------------------------------------------------------------*/ X/* */ X/*----------------------------------------------------------------------*/ X X Xcopy_file (ifp, ofp, size) X FILE *ifp, *ofp; X long size; X{ X copy_binary_file (ifp, ofp, size, 0); X} X X/*ARGSUSED*/ Xint decode_stored_crc (ifp, ofp, original_size, name) X FILE *ifp, *ofp; X long original_size; X char *name; X{ X init_crc (); X X if (text_mode) X { X read_generic_text_file (ifp, ofp, original_size, 1); X return crc_value; X } X else X { X copy_binary_file (ifp, ofp, original_size, 1); X return crc_value; X } X} X X/*ARGSUSED*/ Xint decode_stored_nocrc (ifp, ofp, original_size, name) X FILE *ifp, *ofp; X long original_size; X char *name; X{ X if (text_mode) X { X read_generic_text_file (ifp, ofp, original_size, 0); X return 0; /* DUMMY */ X } X else X { X copy_binary_file (ifp, ofp, original_size, 0); X } X return 0; /* DUMMY */ X} X Xint encode_stored_crc (ifp, ofp, size, original_size_var, write_size_var) X FILE *ifp, *ofp; X long size; X long *original_size_var; X long *write_size_var; X{ X init_crc (); X X if (text_mode) X { X write_generic_text_file (ifp, ofp, size); X *original_size_var = *write_size_var = crc_size; X return crc_value; X } X else X { X copy_binary_file (ifp, ofp, size, 1); X *original_size_var = size; X *write_size_var = size; X return crc_value; X } X} SHAR_EOF chmod 0666 lhio.c || echo "restore of lhio.c fails" echo "x - extracting lhio.h (Text)" sed 's/^X//' << 'SHAR_EOF' > lhio.h && X/*----------------------------------------------------------------------*/ X/* File I/O module for LHarc UNIX */ X/* */ X/* Copyright(C) MCMLXXXIX Yooichi.Tagawa */ X/* */ X/* V0.00 Original 1989.06.25 Y.Tagawa */ X/* V0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa */ X/*----------------------------------------------------------------------*/ X Xextern int text_mode; X Xextern unsigned int crc_table[0x100]; Xextern unsigned int crc_value; Xextern int crc_getc_cashe; Xextern FILE *crc_infile, *crc_outfile; Xextern long crc_size; X X X#define CRC_CHAR(c) \ X{ register unsigned int ctmp = crc_value ^ c; \ X crc_value = (ctmp >> 8) ^ crc_table [ ctmp & 0xff ]; } X X X X#if defined (__GNUC__) X/*#define inlnie*/ X X/* DECODING */ X/* '0D0A' -> '0A' conversion and strip '1A' when text_mode */ Xstatic inline putc_crc (int c) X{ X CRC_CHAR (c); X if (!text_mode || (c != 0x0d && c != 0x1a)) X { X putc (c, crc_outfile); X } X} X X/* ENCODING */ X/* '0A' -> '0D0A' conversion when text_mode */ Xstatic inline int getc_crc () X{ X int c; X X if (crc_getc_cashe != EOF) X { X c = crc_getc_cashe; X crc_getc_cashe = EOF; X CRC_CHAR (c); X crc_size++; X } X else if ((c = getc (crc_infile)) != EOF) X { X if (text_mode && c == 0x0a) X { X crc_getc_cashe = c; X c = 0x0d; X } X CRC_CHAR (c); X crc_size++; X } X return c; X} X#endif SHAR_EOF chmod 0666 lhio.h || echo "restore of lhio.h fails" echo "x - extracting lzhuf.c (Text)" sed 's/^X//' << 'SHAR_EOF' > lzhuf.c && X/*----------------------------------------------------------------------*/ X/* lzhuf.c : Encoding/Decoding module for LHarc */ X/* */ X/* LZSS Algorithm Haruhiko.Okumura */ X/* Adaptic Huffman Encoding 1989.05.27 Haruyasu.Yoshizaki */ X/* */ X/* */ X/* Modified for UNIX LHarc V0.01 1989.05.28 Y.Tagawa */ X/* Modified for UNIX LHarc V0.02 1989.05.29 Y.Tagawa */ X/* Modified for UNIX LHarc V0.03 1989.07.02 Y.Tagawa */ X/*----------------------------------------------------------------------*/ X X/* Use ANSI sequences for using only one line per file but X * indicator dots on next line */ X/* #define ANSI */ X X#ifndef ANSI X#define DOT '.' X#define BALL 'o' X#else X#define DOT 249 X#define BALL 3 X#define CURSORUP "\033[A" X#define ERASEEOL "\033[K" X#endif X X#include <stdio.h> X X#ifndef SELFMAIN X#include "lhio.h" X#else X#define EXIT_SUCCESS 0 X#define EXIT_FAILURE 1 X#endif X X X XFILE *infile, *outfile; Xlong textsize, codesize; X X X#define INDICATOR_THRESHOLD 4096L X#define MAX_INDICATOR_COUNT 78 Xlong indicator_count; Xlong indicator_threshold; X X#ifdef SELFMAIN Xint quiet = 0; X#else Xextern int quiet; Xextern int output_to_test; X#endif X X X#ifdef SELFMAIN X#define SETUP_PUTC_CRC(fp) /* nothing */ X#define SETUP_GETC_CRC(fp) /* nothing */ X#define PUTC_CRC(c) putc((c),(outfile)) X#define GETC_CRC() getc(infile) X#define END_PUTC_CRC() X#define END_GETC_CRC() X#else X#define SETUP_PUTC_CRC(fp) crc_outfile = fp X#define SETUP_GETC_CRC(fp) crc_infile = fp X#define PUTC_CRC(c) putc_crc(c) X#define GETC_CRC() getc_crc() X#define END_PUTC_CRC() X#define END_GETC_CRC() X#endif X X X X X#ifdef SELFMAIN Xvoid Error (message) X char *message; X{ X printf("\n%s\n", message); X exit(EXIT_FAILURE); X} X#endif X X/*----------------------------------------------------------------------*/ X/* */ X/* LZSS ENCODING */ X/* */ X/*----------------------------------------------------------------------*/ X X#define N 4096 /* buffer size */ X#define F 60 /* pre-sence buffer size */ X#define THRESHOLD 2 X#define NIL N /* term of tree */ X Xunsigned char text_buf[N + F - 1]; Xunsigned int match_position, match_length; Xint lson[N + 1], rson[N + 1 + N], dad[N + 1]; Xunsigned char same[N + 1]; X X X/* Initialize Tree */ XInitTree () X{ X register int *p, *e; X X for (p = rson + N + 1, e = rson + N + N; p <= e; ) X *p++ = NIL; X for (p = dad, e = dad + N; p < e; ) X *p++ = NIL; X} X X X/* Insert to node */ XInsertNode (r) X register int r; X{ X register int p; X int cmp; X register unsigned char *key; X register unsigned int c; X register unsigned int i, j; X X cmp = 1; X key = &text_buf[r]; X i = key[1] ^ key[2]; X i ^= i >> 4; X p = N + 1 + key[0] + ((i & 0x0f) << 8); X rson[r] = lson[r] = NIL; X match_length = 0; X i = j = 1; X for ( ; ; ) { X if (cmp >= 0) { X if (rson[p] != NIL) { X p = rson[p]; X j = same[p]; X } else { X rson[p] = r; X dad[r] = p; X same[r] = i; X return; X } X } else { X if (lson[p] != NIL) { X p = lson[p]; X j = same[p]; X } else { X lson[p] = r; X dad[r] = p; X same[r] = i; X return; X } X } X X if (i > j) { X i = j; X cmp = key[i] - text_buf[p + i]; X } else X if (i == j) { X for (; i < F; i++) X if ((cmp = key[i] - text_buf[p + i]) != 0) X break; X } X X if (i > THRESHOLD) { X if (i > match_length) { X match_position = ((r - p) & (N - 1)) - 1; X if ((match_length = i) >= F) X break; X } else X if (i == match_length) { X if ((c = ((r - p) & (N - 1)) - 1) < match_position) { X match_position = c; X } X } X } X } X same[r] = same[p]; X dad[r] = dad[p]; X lson[r] = lson[p]; X rson[r] = rson[p]; X dad[lson[p]] = r; X dad[rson[p]] = r; X if (rson[dad[p]] == p) X rson[dad[p]] = r; X else X lson[dad[p]] = r; X dad[p] = NIL; /* remove p */ X} X X Xlink (n, p, q) X int n, p, q; X{ X register unsigned char *s1, *s2, *s3; X if (p >= NIL) { X same[q] = 1; X return; X } X s1 = text_buf + p + n; X s2 = text_buf + q + n; X s3 = text_buf + p + F; X while (s1 < s3) { X if (*s1++ != *s2++) { X same[q] = s1 - 1 - text_buf - p; X return; X } X } X same[q] = F; X} X X Xlinknode (p, q, r) X int p, q, r; X{ X int cmp; X X if ((cmp = same[q] - same[r]) == 0) { X link(same[q], p, r); X } else if (cmp < 0) { X same[r] = same[q]; X } X} X XDeleteNode (p) X register int p; X{ X register int q; X X if (dad[p] == NIL) X return; /* has no linked */ X if (rson[p] == NIL) { X if ((q = lson[p]) != NIL) X linknode(dad[p], p, q); X } else X if (lson[p] == NIL) { X q = rson[p]; X linknode(dad[p], p, q); X } else { X q = lson[p]; X if (rson[q] != NIL) { X do { X q = rson[q]; X } while (rson[q] != NIL); X if (lson[q] != NIL) X linknode(dad[q], q, lson[q]); X link(1, q, lson[p]); X rson[dad[q]] = lson[q]; X dad[lson[q]] = dad[q]; X lson[q] = lson[p]; X dad[lson[p]] = q; X } X link(1, dad[p], q); X link(1, q, rson[p]); X rson[q] = rson[p]; X dad[rson[p]] = q; X } X dad[q] = dad[p]; X if (rson[dad[p]] == p) X rson[dad[p]] = q; X else X lson[dad[p]] = q; X dad[p] = NIL; X} X X/*----------------------------------------------------------------------*/ X/* */ X/* HUFFMAN ENCODING */ X/* */ X/*----------------------------------------------------------------------*/ X X#define N_CHAR (256 - THRESHOLD + F) /* {code : 0 .. N_CHAR-1} */ X#define T (N_CHAR * 2 - 1) /* size of table */ X#define R (T - 1) /* root position */ X#define MAX_FREQ 0x8000 /* tree update timing from frequency */ X Xtypedef unsigned char uchar; X X X X/* TABLE OF ENCODE/DECODE for upper 6bits position information */ X X/* for encode */ Xuchar p_len[64] = { X 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, X 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 X}; X Xuchar p_code[64] = { X 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68, X 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C, X 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, X 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, X 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE, X 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, X 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, X 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF X}; X X/* for decode */ Xuchar d_code[256] = { X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, X 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, X 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, X 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, X 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, X 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, X 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, X 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, X 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, X 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, X 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, X 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, X 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, X 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, X 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, X 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, X 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, X 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, X 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, X 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, X 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, X 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, X 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, X 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, X 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, X}; X Xuchar d_len[256] = { X 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, X 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, X 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, X 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, X 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, X 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, X 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, X 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, X 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, X 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, X 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, X 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, X}; X Xunsigned freq[T + 1]; /* frequency table */ X Xint prnt[T + N_CHAR]; /* points to parent node */ X/* notes : X prnt[T .. T + N_CHAR - 1] used by X indicates leaf position that corresponding to code */ X Xint son[T]; /* points to son node (son[i],son[i+]) */ X Xunsigned getbuf = 0; Xuchar getlen = 0; X X X/* get one bit */ X/* returning in Bit 0 */ Xint GetBit () X{ X register unsigned int dx = getbuf; X register unsigned int c; X X if (getlen <= 8) X { X c = getc (infile); X if ((int)c < 0) c = 0; X dx |= c << (8 - getlen); X getlen += 8; X } X getbuf = dx << 1; X getlen--; X return (dx & 0x8000) ? 1 : 0; X} X X/* get one byte */ X/* returning in Bit7...0 */ Xint GetByte () X{ X register unsigned int dx = getbuf; X register unsigned c; X X if (getlen <= 8) { X c = getc (infile); X if ((int)c < 0) c = 0; X dx |= c << (8 - getlen); X getlen += 8; X } X getbuf = dx << 8; X getlen -= 8; X return (dx >> 8) & 0xff; X} X X/* get N bit */ X/* returning in Bit(N-1)...Bit 0 */ Xint GetNBits (n) X register unsigned int n; X{ X register unsigned int dx = getbuf; X register unsigned int c; X static int mask[17] = { X 0x0000, X 0x0001, 0x0003, 0x0007, 0x000f, X 0x001f, 0x003f, 0x007f, 0x00ff, X 0x01ff, 0x03ff, 0x07ff, 0x0fff, X 0x1fff, 0x3fff, 0x0fff, 0xffff }; X static int shift[17] = { X 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; X X if (getlen <= 8) X { X c = getc (infile); X if ((int)c < 0) c = 0; X dx |= c << (8 - getlen); X getlen += 8; X } X getbuf = dx << n; X getlen -= n; X return (dx >> shift[n]) & mask[n]; X} X Xunsigned putbuf = 0; Xuchar putlen = 0; X X/* output C bits */ XPutcode (l, c) X register int l; X register unsigned int c; X{ X register len = putlen; X register unsigned int b = putbuf; X b |= c >> len; X if ((len += l) >= 8) { X putc (b >> 8, outfile); X if ((len -= 8) >= 8) { X putc (b, outfile); X codesize += 2; X len -= 8; X b = c << (l - len); X } else { X b <<= 8; X codesize++; X } X } X putbuf = b; X putlen = len; X} X X X/* Initialize tree */ X XStartHuff () X{ X register int i, j; X X for (i = 0; i < N_CHAR; i++) { X freq[i] = 1; X son[i] = i + T; X prnt[i + T] = i; X } X i = 0; j = N_CHAR; X while (j <= R) { X freq[j] = freq[i] + freq[i + 1]; X son[j] = i; X prnt[i] = prnt[i + 1] = j; X i += 2; j++; X } X freq[T] = 0xffff; X prnt[R] = 0; X putlen = getlen = 0; X putbuf = getbuf = 0; X} X X X/* reconstruct tree */ Xreconst () X{ X register int i, j, k; X register unsigned f; X X /* correct leaf node into of first half, X and set these freqency to (freq+1)/2 */ X j = 0; X for (i = 0; i < T; i++) { X if (son[i] >= T) { X freq[j] = (freq[i] + 1) / 2; X son[j] = son[i]; X j++; X } X } X /* build tree. Link sons first */ X for (i = 0, j = N_CHAR; j < T; i += 2, j++) { X k = i + 1; X f = freq[j] = freq[i] + freq[k]; X for (k = j - 1; f < freq[k]; k--); X k++; X { register unsigned *p, *e; X for (p = &freq[j], e = &freq[k]; p > e; p--) X p[0] = p[-1]; X freq[k] = f; X } X { register int *p, *e; X for (p = &son[j], e = &son[k]; p > e; p--) X p[0] = p[-1]; X son[k] = i; X } X } X /* link parents */ X for (i = 0; i < T; i++) { X if ((k = son[i]) >= T) { X prnt[k] = i; X } else { X prnt[k] = prnt[k + 1] = i; X } X } X} X X X/* update given code's frequency, and update tree */ X Xupdate (c) X unsigned int c; X{ X register unsigned *p; X register int i, j, k, l; X X if (freq[R] == MAX_FREQ) { X reconst(); X } X c = prnt[c + T]; X do { X k = ++freq[c]; X X /* swap nodes when become wrong frequency order. */ X if (k > freq[l = c + 1]) { X for (p = freq+l+1; k > *p++; ) ; X l = p - freq - 2; X freq[c] = p[-2]; X p[-2] = k; X X i = son[c]; X prnt[i] = l; X if (i < T) prnt[i + 1] = l; X X j = son[l]; X son[l] = i; X X prnt[j] = c; X if (j < T) prnt[j + 1] = c; X son[c] = j; X X c = l; X } X } while ((c = prnt[c]) != 0); /* loop until reach to root */ X} X X/* unsigned code, len; */ X XEncodeChar (c) X unsigned c; X{ X register int *p; X register unsigned long i; X register int j, k; X X i = 0; X j = 0; X p = prnt; X k = p[c + T]; X X /* trace links from leaf node to root */ X do { X i >>= 1; X X /* if node index is odd, trace larger of sons */ X if (k & 1) i += 0x80000000; X X j++; X } while ((k = p[k]) != R) ; X if (j > 16) { X Putcode(16, (unsigned int)(i >> 16)); X Putcode(j - 16, (unsigned int)i); X } else { X Putcode(j, (unsigned int)(i >> 16)); X } X/* code = i; */ X/* len = j; */ X update(c); X} X XEncodePosition (c) X unsigned c; X{ X unsigned i; X X /* output upper 6bit from table */ X i = c >> 6; X Putcode((int)(p_len[i]), (unsigned int)(p_code[i]) << 8); X X /* output lower 6 bit */ X Putcode(6, (unsigned int)(c & 0x3f) << 10); X} X XEncodeEnd () X{ X if (putlen) { X putc(putbuf >> 8, outfile); X codesize++; X } X} X Xint DecodeChar () X{ X register unsigned c; X X c = son[R]; X X /* trace from root to leaf, X got bit is 0 to small(son[]), 1 to large (son[]+1) son node */ X while (c < T) { X c += GetBit(); X c = son[c]; X } X c -= T; X update(c); X return c; X} X Xint DecodePosition () X{ X unsigned i, j, c; X X /* decode upper 6bit from table */ X i = GetByte(); X c = (unsigned)d_code[i] << 6; X j = d_len[i]; X X /* get lower 6bit */ X j -= 2; X return c | (((i << j) | GetNBits (j)) & 0x3f); X} X X XEncode () X{ X register int i, c, len, r, s, last_match_length; X X if (textsize == 0) X return; X X textsize = 0; X StartHuff(); X InitTree(); X s = 0; X r = N - F; X for (i = s; i < r; i++) X text_buf[i] = ' '; X for (len = 0; len < F && (c = GETC_CRC()) != EOF; len++) X text_buf[r + len] = c; X textsize = len; X for (i = 1; i <= F; i++) X InsertNode(r - i); X InsertNode(r); X do { X if (match_length > len) X match_length = len; X if (match_length <= THRESHOLD) { X match_length = 1; X EncodeChar(text_buf[r]); X } else { X EncodeChar(255 - THRESHOLD + match_length); X EncodePosition(match_position); X } X last_match_length = match_length; X for (i = 0; i < last_match_length && X (c = GETC_CRC()) != EOF; i++) { X DeleteNode(s); X text_buf[s] = c; X if (s < F - 1) X text_buf[s + N] = c; X s = (s + 1) & (N - 1); X r = (r + 1) & (N - 1); X InsertNode(r); X } X X textsize += i; X if ((textsize > indicator_count) && !quiet) { X putchar (BALL); X fflush (stdout); X indicator_count += indicator_threshold; X } X while (i++ < last_match_length) { X DeleteNode(s); X s = (s + 1) & (N - 1); X r = (r + 1) & (N - 1); X if (--len) InsertNode(r); X } X } while (len > 0); X EncodeEnd(); X END_GETC_CRC (); X} X XDecode () X{ X register int i, j, k, r, c; X register long count; X X#ifdef SELFMAIN X if (textsize == 0) X return; X#endif X StartHuff(); X for (i = 0; i < N - F; i++) X text_buf[i] = ' '; X r = N - F; X for (count = 0; count < textsize; ) { X c = DecodeChar(); X if (c < 256) { X PUTC_CRC (c); X text_buf[r++] = c; X r &= (N - 1); X count++; X } else { X i = (r - DecodePosition() - 1) & (N - 1); X j = c - 255 + THRESHOLD; X for (k = 0; k < j; k++) { X c = text_buf[(i + k) & (N - 1)]; X PUTC_CRC (c); X text_buf[r++] = c; X r &= (N - 1); X count++; X } X } X X if (!quiet && (count > indicator_count)) { X putchar (BALL); X fflush (stdout); X indicator_count += indicator_threshold; X } X } X END_PUTC_CRC (); X} X X X/*----------------------------------------------------------------------*/ X/* */ X/* LARC */ X/* */ X/*----------------------------------------------------------------------*/ X X#define F_OLD 18 /* look ahead buffer size for LArc */ X X/* intialize buffer for LArc type 5 */ XInitBuf () X{ X register unsigned char *p = text_buf; X register int i, j; X for (i = 0; i < 256; i ++) X for (j = 0; j < 13; j ++) X *p ++ = i; X for (i = 0; i < 256; i ++) X *p ++ = i; X for (i = 0; i < 256; i ++) X *p ++ = 255 - i; X for (i = 0; i < 128; i ++) X *p ++ = 0; X for (i = 0; i < 128; i ++) X *p ++ = 0x20; X} X X/* Decode LArc type 5 */ XDecodeOld () X{ X register int si, di; X register long count; X int dl, dh, al, cx; X if (textsize == 0) X return; X X InitBuf (); X di = N - F_OLD; X dl = 0x80; X X for (count = 0; count < textsize; ) { X dl = ((dl << 1) | (dl >> 7)) & 0xff; X if (dl & 0x01) X dh = getc (infile); X al = getc (infile); X if ((dh & dl) != 0) { X PUTC_CRC (al); X text_buf[di] = al; X di = (di + 1) & (N - 1); X count ++; X } else { X cx = getc (infile); X si = (al & 0x00ff) | ((cx << 4) & 0x0f00); X cx = (cx & 0x000f) + 3; X count += cx; X do { X text_buf[di] = al = text_buf[si]; X PUTC_CRC (al); X si = (si + 1) & (N - 1); X di = (di + 1) & (N - 1); X } while (--cx != 0) ; X } X X if (!quiet && (count > indicator_count)) { X putchar (BALL); X fflush (stdout); X indicator_count += indicator_threshold; X } X } X END_PUTC_CRC (); X} X X X X/*----------------------------------------------------------------------*/ X/* */ X/* Global Entries for Archiver Driver */ X/* */ X/*----------------------------------------------------------------------*/ X X Xstart_indicator (name, size, msg) X char *name; X long size; X char *msg; X{ X long i; X int m; X X if (quiet) X return; X X#ifdef ANSI X m = MAX_INDICATOR_COUNT; X#else X m = MAX_INDICATOR_COUNT - strlen (name); X#endif X if (m < 0) X m = 3; /* (^_^) */ X X#ifdef ANSI X printf ("\r%s - %s:\n", name, msg); X#else X printf ("\r%s - %s : ", name, msg); X#endif X X indicator_threshold = X ((size + (m * INDICATOR_THRESHOLD - 1)) / X (m * INDICATOR_THRESHOLD) * X INDICATOR_THRESHOLD); X X /* bug fix for files with size==0 28.03.1990 SB */ X if (indicator_threshold == 0) X indicator_threshold = INDICATOR_THRESHOLD; X /************************************************/ X X i = ((size + (indicator_threshold - 1)) / indicator_threshold); X while (i--) X putchar (DOT); X indicator_count = 0; X#ifdef ANSI X printf ("\r%s%s - %s:\n", CURSORUP, name, msg); X#else X printf ("\r%s - %s : ", name, msg); X#endif X fflush (stdout); X} X Xfinish_indicator2 (name, msg, pcnt) X char *name; X char *msg; X int pcnt; X{ X if (quiet) X return; X X if (pcnt > 100) pcnt = 100; /* (^_^) */ X#ifdef ANSI X printf ("\r%s%s - %s(%d%%)\n%s", CURSORUP, name, msg, pcnt, ERASEEOL); X#else X printf ("\r%s - %s(%d%%)\n", name, msg, pcnt); X#endif X fflush (stdout); X} X Xfinish_indicator (name, msg) X char *name; X char *msg; X{ X if (quiet) X return; X X#ifdef ANSI X printf ("\r%s%s - %s\n%s", CURSORUP, name, msg, ERASEEOL); X#else X printf ("\r%s - %s\n", name, msg); X#endif X fflush (stdout); X} X X X#ifndef SELFMAIN Xint encode_lzhuf (infp, outfp, size, original_size_var, packed_size_var, name) X FILE *infp; X FILE *outfp; X long size; X long *original_size_var; X long *packed_size_var; X char *name; X{ X infile = infp; X outfile = outfp; X SETUP_GETC_CRC(infp); X textsize = size; X codesize = 0; X init_crc (); X start_indicator (name, size, "Freezing"); X Encode (); X finish_indicator2 (name, "Frozen", X (int)((codesize * 100L) / crc_size)); X *packed_size_var = codesize; X *original_size_var = crc_size; X return crc_value; X} X Xint decode_lzhuf (infp, outfp, original_size, name) X FILE *infp; X FILE *outfp; X long original_size; X char *name; X{ X infile = infp; X outfile = outfp; X SETUP_PUTC_CRC(outfp); X textsize = original_size; X init_crc (); X start_indicator (name, original_size, X (output_to_test ? "Testing" : "Melting")); X Decode (); X finish_indicator (name, (output_to_test ? "Tested " : "Melted ")); X return crc_value; X} X X Xint decode_larc (infp, outfp, original_size, name) X FILE *infp, *outfp; X long original_size; X char *name; X{ X infile = infp; X outfile = outfp; X SETUP_PUTC_CRC(outfp); X textsize = original_size; X init_crc (); X start_indicator (name, original_size, X (output_to_test ? "Testing" : "Melting")); X DecodeOld (); X finish_indicator (name, (output_to_test ? "Tested " : "Melted ")); X return crc_value; X} X#endif X X#ifdef SELFMAIN Xint main (argc, argv) X int argc; X char *argv[]; X{ X char *s; X int i; X X indicator_count = 0; X indicator_threshold = 1024; X textsize = codesize = 0; X if (argc != 4) { X printf ("\ Xusage: lzhuf e in_file out_file (packing)\n\ X lzhuf d in_file out_file (unpacking)\n"); X return EXIT_FAILURE; X } X if ((s = argv[1], ((*s != 'e') && (*s != 'd')) || s[1] != '\0') || X (s = argv[2], (infile = fopen(s, "rb")) == NULL) || X (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) { X printf("??? %s\n", s); X return EXIT_FAILURE; X } X if (argv[1][0] == 'e') { X /* Get original text size and output it */ X fseek(infile, 0L, 2); X textsize = ftell(infile); X rewind (infile); X if (fwrite(&textsize, sizeof textsize, 1, outfile) < 1) X Error("cannot write"); X X start_indicator (argv[2], textsize, "Freezing"); X Encode(); X finith_indicator2 (argv[2], "Frozen", X (int)((codesize * 100L) / textsize)); X X printf("input : %ld bytes\n", textsize); X printf("output: %ld bytes\n", codesize); X } else { X /* Read original text size */ X if (fread(&textsize, sizeof textsize, 1, infile) < 1) X Error("cannot read"); X X start_indicator (argv[2], textsize, "Melting"); X Decode(); X finish_indicator (argv[2], "Melted "); X } X fclose(infile); X fclose(outfile); X return EXIT_SUCCESS; X} X#endif X X X/* These lines are used in GNU-Emacs */ X/* Local Variables: */ X/* comment-column:40 */ X/* tab-width:8 */ X/* c-indent-level:8 */ X/* c-continued-statement-offset:8 */ X/* c-argdecl-indent:8 */ X/* End: */ SHAR_EOF chmod 0666 lzhuf.c || echo "restore of lzhuf.c fails" echo "x - extracting mktemp.c (Text)" sed 's/^X//' << 'SHAR_EOF' > mktemp.c && X/* MKTEMP.C using TMP environment variable */ X X#include <stdio.h> X#include <stdlib.h> X#include <string.h> X#include <io.h> X Xvoid Mktemp(char *file) X{ X char fname[32], *tmp; X X tmp = getenv("TMP"); X X if ( tmp != NULL ) X { X strcpy(fname, file); X strcpy(file, tmp); X X if ( file[strlen(file) - 1] != '\\' ) X strcat(file, "\\"); X X strcat(file, fname); X } X X mktemp(file); X} X X/* End of MKTEMP.C */ SHAR_EOF chmod 0666 mktemp.c || echo "restore of mktemp.c fails" echo "x - extracting pipes.c (Text)" sed 's/^X//' << 'SHAR_EOF' > pipes.c && X/* a simulation for the Unix popen() and pclose() calls on MS-DOS */ X/* only one pipe can be open at a time */ X X#include <stdio.h> X#include <stdlib.h> X#include <string.h> X Xstatic char pipename[128], command[128]; Xstatic int wrpipe; X Xextern void Mktemp(char *); X XFILE *popen(char *cmd, char *flags) X{ X wrpipe = (strchr(flags, 'w') != NULL); X X if ( wrpipe ) X { X strcpy(command, cmd); X strcpy(pipename, "~WXXXXXX"); X Mktemp(pipename); X return fopen(pipename, flags); /* ordinary file */ X } X else X { X strcpy(pipename, "~RXXXXXX"); X Mktemp(pipename); X strcpy(command, cmd); X strcat(command, ">"); X strcat(command, pipename); X system(command); X return fopen(pipename, flags); /* ordinary file */ X } X} X Xint pclose(FILE *pipe) X{ X int rc; X X if ( fclose(pipe) == EOF ) X return EOF; X X if ( wrpipe ) X { X if ( command[strlen(command) - 1] == '!' ) X command[strlen(command) - 1] = 0; X else X strcat(command, "<"); X X strcat(command, pipename); X rc = system(command); X unlink(pipename); X return rc; X } X else X { X unlink(pipename); X return 0; X } X} SHAR_EOF chmod 0666 pipes.c || echo "restore of pipes.c fails" rm -f s2_seq_.tmp echo "You have unpacked the last part" exit 0 -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) VMS is a text-only adventure game. If you win you can use unix.