Path: utzoo!utgpu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!rpi!crdgw1!crdos1!davidsen From: davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) Newsgroups: alt.sources Subject: lharc for unix (01/02) Keywords: lharc Message-ID: <3006@crdos1.crd.ge.COM> Date: 6 Dec 90 15:03:05 GMT Distribution: alt Organization: GE Corp R&D Center Lines: 2450 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 '' 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 X#include X#include X#include X#include X X#include 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 X#include X#include X#include X#include X X#define INCL_NOPM X#include 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 X#include X#include X#include X#include X X#ifdef PROF X#include X#endif X X#ifdef M_XENIX X#include X#define ftruncate chsize X#endif X X#define STRICT X#define FASTCOPY X X#ifdef MSDOS X#include 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 X#include 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 X#endif X X/* #include */ X#include X X X/*----------------------------------------------------------------------*/ X/* DIRECTORY ACCESS STUFF */ X/*----------------------------------------------------------------------*/ X#ifndef NODIRECTORY X#ifdef SYSV_SYSTEM_DIR X X#include 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 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), , 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 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.