lharc for unix (01/02)
Wm E Davidsen Jr
davidsen at crdos1.crd.ge.COM
Fri Dec 7 02:03:05 AEST 1990
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 at 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 at 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 at 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 at 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 at crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
VMS is a text-only adventure game. If you win you can use unix.
More information about the Alt.sources
mailing list