[alt.sources] lharc for unix

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (12/06/90)

  Here is a versions of lharc I have hacked to run cleanly on a large
number of systems, including Xenix, Sun[34], Encore, and Ultrix.

#!/bin/sh
# shar:	Shell Archiver  (v1.29)
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  Makefile
#	  README
#	  README.1st
#	  clharc.cs
#	  clharc.def
#	  dir.h
#	  dir_dos.c
#	  dir_os2.c
#	  lharc.c
#	  lharc.doc
#	  lhdir.c
#	  lhdir.h
#	  lhio.c
#	  lhio.h
#	  lzhuf.c
#	  mktemp.c
#	  pipes.c
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X# Makefile for LHArc UNIX
X#	Copyright(C) MCMLXXXIX  Yooichi.Tagawa
X# V0.01  Alpha Version				1989.05.28  Y.Tagawa
X# V0.02  Alpha Version R2			1989.05.29  Y.Tagawa
X# V0.03  Release #3  Beta Version		1989.07.02  Y.Tagawa
X
X#-----------------------------------------------------------------------
X# DIRECTORY ACCESS DEPENDENDS...
X#  The default (no need swtich) is your machine has
X#  opendir(),readdir(),closedir() library and 'direct' structure used.
X#  If your machine has no opendir (), readdir (), closedir ()
X#	-DNONSYSTEM_DIR_LIBRARY
X#  and add lhdir.o into OBJS macro (see bellow)
X#  If your machine are 'dirent' (not 'direct') structure used,
X#	-DSYSV_SYSTEM_DIR
X#  Otherwise "Give up!"
X#	-DNODIRECTORY
X#
X#-----------------------------------------------------------------------
X# MEMORY ACCESS STUFF
X#  Your machine has no BSTRING library (bcmp,bcopy,bzero).
X#	-DNOBSTRING
X#
X#-----------------------------------------------------------------------
X# TIME STUFF
X#  Your include file '<sys/time.h>' has no 'struct tm',  define this.
X#	-DSYSTIME_HAS_NO_TM
X#  If you are running on a BSD system,
X#       -DBSD
X#
X
X# most of 4.[23]BSD
X#	- vax 4.[23]BSD, SONY NEWS 4.[23]BSD etc.
X#SWITCHIES	=
X#OBJS		= lharc.o lzhuf.o lhio.o
X
X# sample of System-V
X#	- NEC EWS4800
XSWITCHIES	= -DSYSV_SYSTEM_DIR -DSYSTIME_HAS_NO_TM -DNOBSTRING
XOBJS		= lharc.o lzhuf.o lhio.o # lhdir.o
X
XCC		= cc
XCFLAGS		= $(SWITCHIES)
XLDFLAGS		= -lx
X
X#	Xlharc is test binary.  Please rename to lharc at install.
X#	(see install target)
Xall:	xlharc
X
Xxlharc	: $(OBJS)
X	$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS)
X
X#	For Debugging LzHuff module.
Xlzhuf	: lzhuf.c
X	$(CC) $(CFLAGS) -DSELFMAIN -o $* $*.c
X
Xlzhuf.o	lhio.o	: lhio.h
X
Xclean:
X	rm -f core lharc.o lzhuf.o lhdir.o lhio.o lharc.tar lharc.tar.Z
X
XF286	= -M2l
Xlh286:	$(OBJS)
X	@echo "Removing old object files"
X	rm *.o
X	$(MAKE) CFLAGS="$(F286) $(CFLAGS)" LDFLAGS="$(F286) $(LDFLAGS)"
X	mv xlharc lh286
X	rm *.o
SHAR_EOF
chmod 0666 Makefile || echo "restore of Makefile fails"
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
X								-*- Text -*-
X
XLHarc UNIX V0.03 Release #3  Beta Version
X
X	This is FREEWARE.  But it's BETA-VERSION.
X
X	Please reply to me.
X
X	Sorry, lharc.doc file are written in JAPANESE (Shift-JIS KANJI)
X
X						Thank you.
X
X						Yooichi.Tagawa
X						Nikkei-MIX ID: y.tagawa
X------------------------------------------------------------------------
X
XHOW TO USE:
X	lharc {axevludmcp}[qnft] archive_file [files or directories...]
X
XCOMMAND:
X	KEY	MEANS				Like as (UNIX ar command)
X	--- ------------------------------	------------------------------
X	a    Append to archive.			  ar r AFILE files...
X	x,e  EXtract from archive.		  ar x AFILE [files...]
X	v,l  View/List archive contents.	  ar t AFILE [files...]
X	u    append newer files to archive.	  ar ru AFILE files...
X	d    Delete from archive.		  ar d AFILE files...
X	m    Move to archive.			  ar m AFILE files...
X	c    re-construct new archive file.	  rm AFILE; ar r AFILE files...
X	p    Print to STANDARD-OUTPUT		  ar p AFILE [files...]
X
X
XOPTIONS:
X	q	quiet
X	n	no execute (debugging option)
X	f	force (over write at extract)
X	t	text-mode (this is provisional option)
X
X------------------------------------------------------------------------------
SHAR_EOF
chmod 0666 README || echo "restore of README fails"
echo "x - extracting README.1st (Text)"
sed 's/^X//' << 'SHAR_EOF' > README.1st &&
X                        Partial Revision History
X
XApr 16, 1990 - Bill Davidsen (davidsen@crdos1.crd.ge.com)
X
X  I got this source mailed to me and found that it didn't work on all
Xthe machines I use here. I modified it so it runs on Xenix, Sun3, Sun4,
Xand Ultrix. Since there's a perfectly good DOS version I haven't even
Xtried it there.
X
X  Note: I compiled with the native vendor compiler in all cases,
Xavoiding fancy vectorizing, concurrent, or copylefted compilers.
X
X  Changed the option for output to sysout to be p, to match zoo and arc,
Xso I don't keep typing the wrong thing.
SHAR_EOF
chmod 0644 README.1st || echo "restore of README.1st fails"
echo "x - extracting clharc.cs (Text)"
sed 's/^X//' << 'SHAR_EOF' > clharc.cs &&
X(-W1 lharc.c lhio.c dir_os2.c mktemp.c pipes.c)
X(-W1 -Ox lzhuf.c)
Xsetargv.obj
Xclharc.def
Xclharc.exe
X-as -lb -s0x2000
SHAR_EOF
chmod 0666 clharc.cs || echo "restore of clharc.cs fails"
echo "x - extracting clharc.def (Text)"
sed 's/^X//' << 'SHAR_EOF' > clharc.def &&
XNAME CLHARC WINDOWCOMPAT
XDESCRIPTION 'C-LHarc 1.00 - for MS-DOS and OS/2'
SHAR_EOF
chmod 0666 clharc.def || echo "restore of clharc.def fails"
echo "x - extracting dir.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > dir.h &&
X/*
X * @(#) dir.h 1.4 87/11/06   Public Domain.
X *
X *  A public domain implementation of BSD directory routines for
X *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
X *  August 1897
X *  Ported to OS/2 by Kai Uwe Rommel and added scandir prototype
X *  December 1989
X */
X
X#define	rewinddir(dirp)	seekdir(dirp, 0L)
X
X#define	MAXNAMLEN	12
X
Xstruct direct
X{
X	ino_t	d_ino;			/* a bit of a farce */
X	int	d_reclen;		/* more farce */
X	int	d_namlen;		/* length of d_name */
X        char    d_name[MAXNAMLEN + 1];  /* garentee null termination */
X};
X
Xstruct _dircontents
X{
X	char	*_d_entry;
X	struct _dircontents	*_d_next;
X};
X
Xtypedef struct _dirdesc
X{
X	int		dd_id;	/* uniquely identify each open directory */
X	long		dd_loc;	/* where we are in directory entry is this */
X	struct _dircontents	*dd_contents;	/* pointer to contents of dir */
X	struct _dircontents	*dd_cp;	/* pointer to current position */
X} DIR;
X
Xextern  DIR            *opendir(char *);
Xextern  struct direct  *readdir(DIR *);
Xextern  void            seekdir(DIR *, long);
Xextern  long            telldir(DIR *);
Xextern  void            closedir(DIR *);
X
Xextern  int             scandir(char *, struct direct ***,
X                                int (*)(struct direct *), int (*)());
SHAR_EOF
chmod 0666 dir.h || echo "restore of dir.h fails"
echo "x - extracting dir_dos.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dir_dos.c &&
X/*
X * @(#)dir.c 1.4 87/11/06	Public Domain.
X *
X *  A public domain implementation of BSD directory routines for
X *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
X *  August 1897
X *  Modified to use modern MS C library functions by Kai Uwe Rommel
X *  December 1989
X */
X
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	<sys/dir.h>
X#include	<malloc.h>
X#include	<string.h>
X
X#include        <dos.h>
X
X#ifndef	NULL
X# define	NULL	0
X#endif	/* NULL */
X
X#ifndef	MAXPATHLEN
X# define	MAXPATHLEN	255
X#endif	/* MAXPATHLEN */
X
X/* attribute stuff */
X#define	A_RONLY		0x01
X#define	A_HIDDEN	0x02
X#define	A_SYSTEM	0x04
X#define	A_LABEL		0x08
X#define	A_DIR		0x10
X#define	A_ARCHIVE	0x20
X
X
X#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
X
X#define ATTRIBUTES      (A_DIR)
X/* #define ATTRIBUTES      (A_DIR | A_HIDDEN | A_SYSTEM) */
X/* #define ATTRIBUTES      (A_RONLY | A_SYSTEM | A_DIR) */
X
Xstatic  char    *getdirent(char *);
Xstatic	void	free_dircontents(struct _dircontents *);
X
Xstatic struct find_t find;
X
X
XDIR	*
Xopendir(name)
X	char	*name;
X{
X	struct	stat		statb;
X	DIR			*dirp;
X	char			c;
X	char			*s;
X	struct _dircontents	*dp;
X	char			nbuf[MAXPATHLEN + 1];
X
X	if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
X		return (DIR *) NULL;
X	if (Newisnull(dirp, DIR))
X		return (DIR *) NULL;
X	if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
X		(void) strcat(strcpy(nbuf, name), "\\*.*");
X	else
X		(void) strcat(strcpy(nbuf, name), "*.*");
X	dirp->dd_loc = 0;
X        dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
X
X	if ((s = getdirent(nbuf)) == (char *) NULL)
X		return dirp;
X	do {
X		if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
X			malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
X		{
X			if (dp)
X				free((char *) dp);
X			free_dircontents(dirp->dd_contents);
X			return (DIR *) NULL;
X		}
X		if (dirp->dd_contents)
X			dirp->dd_cp = dirp->dd_cp->_d_next = dp;
X		else
X			dirp->dd_contents = dirp->dd_cp = dp;
X		(void) strcpy(dp->_d_entry, s);
X		dp->_d_next = (struct _dircontents *) NULL;
X        } while ((s = getdirent((char *) NULL)) != (char *) NULL);
X
X	dirp->dd_cp = dirp->dd_contents;
X
X	return dirp;
X}
X
Xvoid
Xclosedir(dirp)
X	DIR	*dirp;
X{
X	free_dircontents(dirp->dd_contents);
X	free((char *) dirp);
X}
X
Xstruct direct	*
Xreaddir(dirp)
X	DIR	*dirp;
X{
X	static	struct direct	dp;
X
X	if (dirp->dd_cp == (struct _dircontents *) NULL)
X		return (struct direct *) NULL;
X	dp.d_namlen = dp.d_reclen =
X		strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
X	strlwr(dp.d_name);		/* JF */
X	dp.d_ino = 0;
X	dirp->dd_cp = dirp->dd_cp->_d_next;
X	dirp->dd_loc++;
X
X	return &dp;
X}
X
Xvoid
Xseekdir(dirp, off)
X	DIR	*dirp;
X	long	off;
X{
X	long			i = off;
X	struct _dircontents	*dp;
X
X	if (off < 0)
X		return;
X	for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
X		;
X	dirp->dd_loc = off - (i + 1);
X	dirp->dd_cp = dp;
X}
X
Xlong
Xtelldir(dirp)
X	DIR	*dirp;
X{
X	return dirp->dd_loc;
X}
X
Xstatic	void
Xfree_dircontents(dp)
X	struct	_dircontents	*dp;
X{
X	struct _dircontents	*odp;
X
X	while (dp) {
X		if (dp->_d_entry)
X			free(dp->_d_entry);
X		dp = (odp = dp)->_d_next;
X		free((char *) odp);
X	}
X}
X
Xstatic char *getdirent(dir)
Xchar *dir;
X{
X  int done;
X
X  if (dir != (char *) NULL)
X    done = _dos_findfirst(dir, ATTRIBUTES, &find);
X  else                                  /* get next entry */
X    done = _dos_findnext(&find);
X
X  if (done==0)
X    return find.name;
X  else
X    return (char *) NULL;
X}
X
X
Xsetfilemode(char *name, unsigned attr)
X{
X  _dos_setfileattr(name, attr);
X}
X
Xgetfilemode(char *name, unsigned *attr)
X{
X  _dos_getfileattr(name, attr);
X}
SHAR_EOF
chmod 0666 dir_dos.c || echo "restore of dir_dos.c fails"
echo "x - extracting dir_os2.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dir_os2.c &&
X/*
X * @(#)dir.c 1.4 87/11/06	Public Domain.
X *
X *  A public domain implementation of BSD directory routines for
X *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
X *  August 1897
X *  Ported to OS/2 by Kai Uwe Rommel
X *  December 1989
X */
X
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	<sys/dir.h>
X#include	<malloc.h>
X#include	<string.h>
X
X#define INCL_NOPM
X#include <os2.h>
X
X#ifndef	NULL
X# define	NULL	0
X#endif	/* NULL */
X
X#ifndef	MAXPATHLEN
X# define	MAXPATHLEN	255
X#endif	/* MAXPATHLEN */
X
X/* attribute stuff */
X#define	A_RONLY		0x01
X#define	A_HIDDEN	0x02
X#define	A_SYSTEM	0x04
X#define	A_LABEL		0x08
X#define	A_DIR		0x10
X#define	A_ARCHIVE	0x20
X
X
X#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
X
X#define ATTRIBUTES      (A_DIR)
X/* #define ATTRIBUTES      (A_DIR | A_HIDDEN | A_SYSTEM) */
X/* #define ATTRIBUTES      (A_RONLY | A_SYSTEM | A_DIR) */
X
Xstatic  char    *getdirent(char *);
Xstatic	void	free_dircontents(struct _dircontents *);
X
Xstatic HDIR hdir;
Xstatic USHORT count;
Xstatic FILEFINDBUF find;
X
X
XDIR	*
Xopendir(name)
X	char	*name;
X{
X	struct	stat		statb;
X	DIR			*dirp;
X	char			c;
X	char			*s;
X	struct _dircontents	*dp;
X	char			nbuf[MAXPATHLEN + 1];
X
X	if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
X		return (DIR *) NULL;
X	if (Newisnull(dirp, DIR))
X		return (DIR *) NULL;
X	if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
X		(void) strcat(strcpy(nbuf, name), "\\*.*");
X	else
X		(void) strcat(strcpy(nbuf, name), "*.*");
X	dirp->dd_loc = 0;
X        dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
X
X	if ((s = getdirent(nbuf)) == (char *) NULL)
X		return dirp;
X	do {
X		if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
X			malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
X		{
X			if (dp)
X				free((char *) dp);
X			free_dircontents(dirp->dd_contents);
X			return (DIR *) NULL;
X		}
X		if (dirp->dd_contents)
X			dirp->dd_cp = dirp->dd_cp->_d_next = dp;
X		else
X			dirp->dd_contents = dirp->dd_cp = dp;
X		(void) strcpy(dp->_d_entry, s);
X		dp->_d_next = (struct _dircontents *) NULL;
X        } while ((s = getdirent((char *) NULL)) != (char *) NULL);
X
X	dirp->dd_cp = dirp->dd_contents;
X
X	return dirp;
X}
X
Xvoid
Xclosedir(dirp)
X	DIR	*dirp;
X{
X	free_dircontents(dirp->dd_contents);
X	free((char *) dirp);
X}
X
Xstruct direct	*
Xreaddir(dirp)
X	DIR	*dirp;
X{
X	static	struct direct	dp;
X
X	if (dirp->dd_cp == (struct _dircontents *) NULL)
X		return (struct direct *) NULL;
X	dp.d_namlen = dp.d_reclen =
X		strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
X	strlwr(dp.d_name);		/* JF */
X	dp.d_ino = 0;
X	dirp->dd_cp = dirp->dd_cp->_d_next;
X	dirp->dd_loc++;
X
X	return &dp;
X}
X
Xvoid
Xseekdir(dirp, off)
X	DIR	*dirp;
X	long	off;
X{
X	long			i = off;
X	struct _dircontents	*dp;
X
X	if (off < 0)
X		return;
X	for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
X		;
X	dirp->dd_loc = off - (i + 1);
X	dirp->dd_cp = dp;
X}
X
Xlong
Xtelldir(dirp)
X	DIR	*dirp;
X{
X	return dirp->dd_loc;
X}
X
Xstatic	void
Xfree_dircontents(dp)
X	struct	_dircontents	*dp;
X{
X	struct _dircontents	*odp;
X
X	while (dp) {
X		if (dp->_d_entry)
X			free(dp->_d_entry);
X		dp = (odp = dp)->_d_next;
X		free((char *) odp);
X	}
X}
X
Xstatic char *getdirent(dir)
Xchar *dir;
X{
X  int done;
X
X  if (dir != (char *) NULL)
X  {                                     /* get first entry */
X    hdir = HDIR_CREATE;
X    count = 1;
X    done = DosFindFirst(dir, &hdir, ATTRIBUTES,
X                        &find, sizeof(find), &count, 0L);
X  }
X  else                                  /* get next entry */
X    done = DosFindNext(hdir, &find, sizeof(find), &count);
X
X  if (done==0)
X    return find.achName;
X  else
X  {
X    DosFindClose(hdir);
X    return (char *) NULL;
X  }
X}
X
X
Xsetfilemode(char *name, unsigned attr)
X{
X  DosSetFileMode(name, attr, 0L);
X}
X
Xgetfilemode(char *name, unsigned *attr)
X{
X  DosQFileMode(name, (PUSHORT) attr, 0L);
X}
SHAR_EOF
chmod 0666 dir_os2.c || echo "restore of dir_os2.c fails"
echo "x - extracting lharc.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > lharc.c &&
X/*----------------------------------------------------------------------*/
X/*		LHarc Archiver Driver for UNIX				*/
X/*									*/
X/*		Copyright(C) MCMLXXXIX  Yooichi.Tagawa			*/
X/*		Thanks to H.Yoshizaki. (MS-DOS LHarc)			*/
X/*									*/
X/*  V0.00  Original				1988.05.23  Y.Tagawa	*/
X/*  V0.01  Alpha Version (for 4.2BSD)		1989.05.28  Y.Tagawa	*/
X/*  V0.02  Alpha Version Rel.2			1989.05.29  Y.Tagawa	*/
X/*  V0.03  Release #3  Beta Version		1989.07.02  Y.Tagawa	*/
X/*  V0.03a Fix few bug                          1989.07.03  Y.Tagawa    */
X/*  V0.04  A lot of bugs fixed, strict mode     1990.01.13  Kai Uwe Rommel */
X/*  V1.00  f and t commands, v option added     1990.01.27  Kai Uwe Rommel */
X/*----------------------------------------------------------------------*/
X
X
X#include <stdio.h>
X#include <ctype.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#ifdef PROF
X#include <profile.h>
X#endif
X
X#ifdef M_XENIX
X#include <sys/fcntl.h>
X#define ftruncate chsize
X#endif
X
X#define STRICT
X#define FASTCOPY
X
X#ifdef MSDOS
X#include <fcntl.h>
Xextern unsigned char _osmode;
Xextern FILE *popen();
Xextern pclose();
X#define ftruncate chsize
X#define mktemp Mktemp
X#define SYSTIME_HAS_NO_TM
X#define NOBSTRING
X#define SYSNAME (_osmode ? "OS/2" : "MS-DOS")
X#define OUR_EXTEND (_osmode ? EXTEND_OS2 : EXTEND_MSDOS)
X#define FILENAME_LENGTH 128
X#define NULLFILE "nul"
X#define TMP_FILENAME_TEMPLATE "lhXXXXXX"
X#define NOT_COMPATIBLE_MODE
X#define RMODE "rb"
X#define WMODE "wb"
X#else
X#include <sys/file.h>
X#include <sys/time.h>
X#define SYSNAME "UNIX"
X#define OUR_EXTEND EXTEND_UNIX
X#define FILENAME_LENGTH	1024
X#define NULLFILE "/dev/null"
X#define RMODE "r"
X#define WMODE "w"
X#endif
X
X#ifdef SYSTIME_HAS_NO_TM
X/* most of System V,  define SYSTIME_HAS_NO_TM */
X#include <time.h>
X#endif
X
X/* #include <strings.h> */
X#include <string.h>
X
X
X/*----------------------------------------------------------------------*/
X/*			DIRECTORY ACCESS STUFF				*/
X/*----------------------------------------------------------------------*/
X#ifndef NODIRECTORY
X#ifdef SYSV_SYSTEM_DIR
X
X#include <dirent.h>
X#define DIRENTRY	struct dirent
X#define NAMLEN(p)	strlen (p->d_name)
X
X#else	/* not SYSV_SYSTEM_DIR */
X
X#ifdef NONSYSTEM_DIR_LIBRARY
X#include "lhdir.h"
X#else	/* not NONSYSTEM_DIR_LIBRARY */
X#include <sys/dir.h>
X#endif	/* not NONSYSTEM_DIR_LIBRARY */
X
X#define DIRENTRY	struct direct
X#define NAMLEN(p)	p->d_namlen
X
Xextern DIR *opendir ();
Xextern struct direct *readdir ();
X
X#endif	/* not SYSV_SYSTEM_DIR */
X#endif
X
X/*----------------------------------------------------------------------*/
X/*			FILE ATTRIBUTES					*/
X/*----------------------------------------------------------------------*/
X
X/* If file mode is not compatible between your Machine/OS and
X   LHarc standard UNIX file mode.
X   (See UNIX Manual stat(1), <sys/stat.h>,
X   and/or below UNIX_* difinitions. ) */
X/* #define NOT_COMPATIBLE_MODE */
X
X
X/*----------------------------------------------------------------------*/
X/*			MEMORY FUNCTIONS 				*/
X/*----------------------------------------------------------------------*/
X
X#ifdef NOBSTRING
X#ifdef __ANSI__
X#include "mem.h"
X#define bcmp(a,b,n) memcmp ((a),(b),(n))
X#define bcopy(s,d,n) memmove((d),(s),(n))
X#define bzero(d,n) memset((d),0,(n))
X#else	/* not __ANSI__ */
X#include "memory.h"
X#define bcmp(a,b,n) memcmp ((a),(b),(n))
X#define bcopy(s,d,n) memcpy ((d),(s),(n))	/* movmem((s),(d),(n)) */
X#define bzero(d,n) memset((d),0,(n))
X#endif	/* not __ANSI__ */
X#endif	/* NOBSTRING */
X
X
X/*----------------------------------------------------------------------*/
X/*			YOUR CUSTOMIZIES				*/
X/*----------------------------------------------------------------------*/
X/* These difinitions are changable to you like. */
X/* #define ARCHIVENAME_EXTENTION	".LZH"		*/
X/* #define TMP_FILENAME_TEMPLATE	"/tmp/lhXXXXXX"	*/
X/* #define BACKUPNAME_EXTENTION		".BAK"		*/
X/* #define MULTIBYTE_CHAR				*/
X
X
X
X#define SJC_FIRST_P(c)			\
X  (((unsigned char)(c) >= 0x80) &&	\
X   (((unsigned char)(c) < 0xa0) ||	\
X    ((unsigned char)(c) >= 0xe0) &&	\
X    ((unsigned char)(c) < 0xfd)))
X#define SJC_SECOND_P(c)			\
X  (((unsigned char)(c) >= 0x40) &&	\
X   ((unsigned char)(c) < 0xfd) &&	\
X   ((ungigned char)(c) != 0x7f))
X
X#ifdef MULTIBYTE_CHAR
X#define MULTIBYTE_FIRST_P	SJC_FIRST_P
X#define MULTIBYTE_SECOND_P	SJC_SECOND_P
X#endif
X
X/*----------------------------------------------------------------------*/
X/*			OTHER DIFINITIONS				*/
X/*----------------------------------------------------------------------*/
X
X#ifndef SEEK_SET
X#define SEEK_SET	0
X#define SEEK_CUR	1
X#define SEEK_END	2
X#endif
X
X
X/* non-integral functions */
Xextern struct tm *localtime ();
Xextern char *getenv ();
Xextern char *malloc ();
Xextern char *realloc ();
X
Xextern int rson[];
X
X/* external variables */
Xextern int errno;
X
X
X#define	FALSE	0
X#define TRUE	1
Xtypedef int boolean;
X
X
X/*----------------------------------------------------------------------*/
X/*		LHarc FILE DIFINITIONS					*/
X/*----------------------------------------------------------------------*/
X#define METHOD_TYPE_STRAGE	5
X#define LZHUFF0_METHOD		"-lh0-"
X#define LZHUFF1_METHOD		"-lh1-"
X#define LARC4_METHOD		"-lz4-"
X#define LARC5_METHOD		"-lz5-"
X
X#define I_HEADER_SIZE			0
X#define I_HEADER_CHECKSUM		1
X#define I_METHOD			2
X#define I_PACKED_SIZE			7
X#define I_ORIGINAL_SIZE			11
X#define I_LAST_MODIFIED_STAMP		15
X#define I_ATTRIBUTE			19
X#define I_NAME_LENGTH			21
X#define I_NAME				22
X
X#define I_CRC				22 /* + name_length */
X#define I_EXTEND_TYPE			24 /* + name_length */
X#define I_MINOR_VERSION			25 /* + name_length */
X#define I_UNIX_LAST_MODIFIED_STAMP	26 /* + name_length */
X#define I_UNIX_MODE			30 /* + name_length */
X#define I_UNIX_UID			32 /* + name_length */
X#define I_UNIX_GID			34 /* + name_length */
X#define I_UNIX_EXTEND_BOTTOM		36 /* + name_length */
X
X
X
X#define EXTEND_GENERIC  0
X#define EXTEND_UNIX	'U'
X#define EXTEND_MSDOS	'M'
X#define EXTEND_MACOS	'm'
X#define EXTEND_OS9	'9'
X#define EXTEND_OS2	'2'
X#define EXTEND_OS68K	'K'
X#define EXTEND_OS386	'3'
X#define EXTEND_HUMAN	'H'
X#define EXTEND_CPM	'C'
X#define EXTEND_FLEX	'F'
X
X#define GENERIC_ATTRIBUTE		0x20
X#define GENERIC_DIRECTORY_ATTRIBUTE	0x10
X
X#define CURRENT_UNIX_MINOR_VERSION	0x00
X
X
X
Xtypedef struct LzHeader {
X  unsigned char		header_size;
X  char			method[METHOD_TYPE_STRAGE];
X  long			packed_size;
X  long			original_size;
X  long			last_modified_stamp;
X  unsigned short	attribute;
X  char			name[256];
X  unsigned short	crc;
X  boolean		has_crc;
X  unsigned char		extend_type;
X  unsigned char		minor_version;
X  /*  extend_type == EXTEND_UNIX  and convert from other type. */
X  time_t		unix_last_modified_stamp;
X  unsigned short	unix_mode;
X  unsigned short	unix_uid;
X  unsigned short	unix_gid;
X} LzHeader;
X
X#define UNIX_FILE_TYPEMASK	0170000
X#define UNIX_FILE_REGULAR	0100000
X#define UNIX_FILE_DIRECTORY	0040000
X#define UNIX_SETUID		0004000
X#define UNIX_SETGID		0002000
X#define UNIX_STYCKYBIT		0001000
X#define UNIX_OWNER_READ_PERM	0000400
X#define UNIX_OWNER_WRITE_PERM	0000200
X#define UNIX_OWNER_EXEC_PERM	0000100
X#define UNIX_GROUP_READ_PERM	0000040
X#define UNIX_GROUP_WRITE_PERM	0000020
X#define UNIX_GROUP_EXEC_PERM	0000010
X#define UNIX_OTHER_READ_PERM	0000004
X#define UNIX_OTHER_WRITE_PERM	0000002
X#define UNIX_OTHER_EXEC_PERM	0000001
X#define UNIX_RW_RW_RW		0000666
X
X#define LZHEADER_STRAGE		256
X
X/*----------------------------------------------------------------------*/
X/*		PROGRAM 						*/
X/*----------------------------------------------------------------------*/
X
X
X#define CMD_UNKNOWN	0
X#define CMD_EXTRACT	1
X#define CMD_APPEND	2
X#define CMD_VIEW	3
X
Xint      cmd = CMD_UNKNOWN;
Xchar     **cmd_filev;
Xint      cmd_filec;
Xchar     *archive_name;
X
Xchar     expanded_archive_name[FILENAME_LENGTH];
Xchar     temporary_name[FILENAME_LENGTH];
Xchar     pager[FILENAME_LENGTH];
X
X
X/* options */
Xboolean	quiet = FALSE;
Xboolean	text_mode = FALSE;
X/*boolean  verbose = FALSE; */
X#ifdef	MSDOS
Xboolean  keepcase = FALSE;	/* all filenames single case */
X#else	/* UNIX */
Xboolean  keepcase = TRUE;	/* don't mess with case of filenames */
X#endif	/* set case options */
Xboolean  noexec = FALSE;	/* debugging option */
Xboolean  force = FALSE;
Xboolean  prof = FALSE;
X
X
X/* view flags */
Xboolean  long_format_listing = FALSE;
X
X/* extract flags */
Xboolean  output_to_test = FALSE;
Xboolean  output_to_stdout = FALSE;
X
X/* append flags */
Xboolean  new_archive = FALSE;
Xboolean  update_if_newer = FALSE;
Xboolean  update_freshen = FALSE;
Xboolean  delete_after_append = FALSE;
Xboolean  delete_from_archive = FALSE;
X
Xboolean  remove_temporary_at_error = FALSE;
X
X
X/*----------------------------------------------------------------------*/
X/* NOTES :	Text File Format					*/
X/*	GENERATOR		NewLine					*/
X/*	[generic]		0D 0A					*/
X/*	[MS-DOS]		0D 0A					*/
X/*	[MacOS]			0D					*/
X/*	[UNIX]			0A					*/
X/*----------------------------------------------------------------------*/
X
Xchar *myname;
X
X
Xvoid userbreak()
X{
X    error("Interrupt.");
X}
X
X
Xmain (argc, argv)
X     int argc;
X     char *argv[];
X{
X  char *p;
X
X  myname = argv[0];
X  signal(SIGINT, userbreak);
X
X#ifdef PROF
X  PROFINIT(PT_USER|PT_USEKP, NULL);
X  PROFCLEAR(PT_USER);
X  PROFON(PT_USER);
X#endif
X
X  if (argc < 3)
X    print_tiny_usage_and_exit ();
X
X  /* commands */
X#ifdef MSDOS
X  switch (tolower(argv[1][0]))
X#else
X  switch (argv[1][0])
X#endif
X    {
X    case 'x':
X    case 'e':
X      cmd = CMD_EXTRACT;
X      break;
X
X    case 't':
X      output_to_test = TRUE;
X      cmd = CMD_EXTRACT;
X      break;
X
X    case 'p':
X      output_to_stdout = TRUE;
X      cmd = CMD_EXTRACT;
X      break;
X
X    case 'c':
X      new_archive = TRUE;
X      cmd = CMD_APPEND;
X      break;
X
X    case 'a':
X      cmd = CMD_APPEND;
X      break;
X
X    case 'd':
X      delete_from_archive = TRUE;
X      cmd = CMD_APPEND;
X      break;
X
X    case 'u':
X      update_if_newer = TRUE;
X      cmd = CMD_APPEND;
X      break;
X
X    case 'f':
X      update_if_newer = update_freshen = TRUE;
X      cmd = CMD_APPEND;
X      break;
X
X    case 'm':
X      delete_after_append = TRUE;
X      cmd = CMD_APPEND;
X      break;
X
X    case 'v':
X      long_format_listing = TRUE;
X      cmd = CMD_VIEW;
X      break;
X
X    case 'l':
X      cmd = CMD_VIEW;
X      break;
X
X    case 'h':
X    default:
X      print_tiny_usage_and_exit ();
X    }
X
X  /* options */
X  p = &argv[1][1];
X  for (p = &argv[1][1]; *p; p++)
X    {
X#ifdef MSDOS
X      switch (tolower(*p))
X#else
X      switch (*p)
X#endif
X	{
X	case 'q':	quiet = TRUE; break;
X	case 'f':	force = TRUE; break;
X/*      case 'p':       prof = TRUE; break; */
X/*      case 'v':       verbose = TRUE; break; */
X        case 'p':       if (p[1] != 0) {
X			    strcpy(pager, p + 1);
X			    *(p + 1) = 0; 
X			}
X			else strcpy(pager, "more");
X			break;
X	case 't':	text_mode = TRUE; break;
X	case 'n':	noexec = TRUE; break;
X
X	default:
X          fprintf (stderr, "unknown option '%c'.\n", *p);
X	  exit (1);
X        }
X    }
X
X  /* archive file name */
X  archive_name = argv[2];
X
X  /* target file name */
X  cmd_filec = argc - 3;
X  cmd_filev = argv + 3;
X  sort_files ();
X
X  switch (cmd)
X    {
X    case CMD_EXTRACT:	cmd_extract ();	break;
X    case CMD_APPEND:	cmd_append ();	break;
X    case CMD_VIEW:	cmd_view ();	break;
X    }
X
X#ifdef PROF
X  PROFOFF(PT_USER);
X  PROFDUMP(PT_USER, "profile.out");
X  PROFFREE(PT_USER);
X#endif
X
X  exit (0);
X}
X
Xprint_tiny_usage_and_exit ()
X{
X  printf("\nC-LHarc for %s Version 1.00   (C) 1989-1990 Y.Tagawa, Kai Uwe Rommel\n%s",
X         "\nUsage: %s {axevlufdmctp}[qnftv] archive_file [files or directories...]\n",
X         SYSNAME, myname);
X  printf("\nCommands:                    Options:\n%s%s%s%s%s%s%s%s%s%s",
X         "  a   Append                   q   quiet\n",
X         "  x,e EXtract                  n   no execute\n",
X         "  v,l View/List                f   force (over write at extract)\n",
X         "  u   Update                   t   files are TEXT files\n",
X         "  f   Freshen                  p<pager>  use file pager for p command\n",
X         "  d   Delete\n",
X         "  m   Move\n",
X         "  c   re-Construct new archive\n",
X         "  t   Test archive\n",
X         "  p   Print to STDOUT\n");
X  exit (1);
X}
X
Xmessage (title, msg)
X     char *title, *msg;
X{
X  fprintf (stderr, "%s ", myname);
X  if (errno == 0)
X    fprintf (stderr, "%s %s\n", title, msg);
X  else
X    perror (msg);
X}
X
Xwarning (msg)
X     char *msg;
X{
X  message ("Warning:", msg);
X}
X
Xerror (msg)
X     char *msg;
X{
X  message ("Error:", msg);
X
X  if (remove_temporary_at_error)
X  {
X#ifdef MSDOS
X    fcloseall();
X#endif
X    unlink (temporary_name);
X  }
X
X  exit (1);
X}
X
Xchar *writting_filename;
Xchar *reading_filename;
X
Xwrite_error ()
X{
X  error (writting_filename);
X}
X
Xread_error ()
X{
X  error (reading_filename);
X}
X
X
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
Xboolean expand_archive_name (dst, src)
X     char *dst, *src;
X{
X  register char *p, *dot;
X
X  strcpy (dst, src);
X
X  for (p = dst, dot = (char*)0; *p; p++)
X    if (*p == '.')
X      dot = p;
X    else if (*p == '/' || *p == '\\')
X      dot = (char*)0;
X
X  if (dot)
X    p = dot;
X
X#ifdef ARCHIVENAME_EXTENTION
X  strcpy (p, ARCHIVENAME_EXTENTION);
X#else
X  strcpy (p, ".lzh");
X#endif
X  return (strcmp (dst, src) != 0);
X}
X
X#ifdef MSDOS
X#define STRING_COMPARE(a,b) stricmp((a),(b))
X#else
X#define STRING_COMPARE(a,b) strcmp((a),(b))
X#endif
X
Xint sort_by_ascii (a, b)
X     char **a, **b;
X{
X  return STRING_COMPARE (*a, *b);
X}
X
Xsort_files ()
X{
X  qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
X}
X
X#ifndef MSDOS
Xchar *strdup (string)
X     char *string;
X{
X  int	len = strlen (string) + 1;
X  char	*p = malloc (len);
X  bcopy (string, p, len);
X  return p;
X}
X#endif
X
X#ifdef NODIRECTORY
X/* please need your imprementation */
Xboolean find_files (name, v_filec, v_filev)
X     char	*name;
X     int	*v_filec;
X     char	***v_filev;
X{
X  return FALSE;			/* DUMMY */
X}
X#else
Xboolean find_files (name, v_filec, v_filev)
X     char	*name;
X     int	*v_filec;
X     char	***v_filev;
X{
X  char		newname[FILENAME_LENGTH];
X  int 		len, n;
X  DIR		*dirp;
X  DIRENTRY	*dp;
X  int           alloc_size = 64; /* any (^_^) */
X  char		**filev;
X  int		filec = 0;
X
X  if ( strcmp(name, ".") == 0 )
X    newname[0] = 0;
X  else
X    strcpy (newname, name);
X
X  len = strlen (newname);
X  dirp = opendir (name);
X
X  if (dirp)
X    {
X      filev = (char**)malloc (alloc_size * sizeof(char *));
X      if (!filev)
X	error ("not enough memory");
X
X      for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
X	{
X	  n = NAMLEN (dp);
X          if (
X#ifndef MSDOS
X              (dp->d_ino != 0) &&
X#endif
X              ((dp->d_name[0] != '.') ||
X                 ((n != 1) &&
X                 ((dp->d_name[1] != '.') ||
X		 (n != 2)))) &&			/* exclude '.' and '..' */
X	      (strcmp (dp->d_name, temporary_name) != 0) &&
X	      (strcmp (dp->d_name, archive_name) != 0))
X	    {
X              if ((len != 0) && (newname[len-1] != '/') && (newname[len-1] != '\\'))
X                {
X#ifdef MSDOS
X                  newname[len] = '\\';
X#else
X                  newname[len] = '/';
X#endif
X		  strncpy (newname+len+1, dp->d_name, n);
X		  newname[len+n+1] = '\0';
X		}
X	      else
X		{
X		  strncpy (newname+len, dp->d_name, n);
X		  newname[len+n] = '\0';
X		}
X
X	      filev[filec++] = strdup (newname);
X	      if (filec == alloc_size)
X		{
X                  alloc_size += 64;
X                  filev = (char**)realloc (filev, alloc_size * sizeof(char *));
X		}
X	    }
X	}
X      closedir (dirp);
X    }
X
X  *v_filev = filev;
X  *v_filec = filec;
X  if (dirp)
X    {
X      qsort (filev, filec, sizeof (char*), sort_by_ascii);
X      return TRUE;
X    }
X  else
X    return FALSE;
X}
X#endif
X
Xfree_files (filec, filev)
X     int	filec;
X     char	**filev;
X{
X  int		i;
X
X  for (i = 0; i < filec; i ++)
X    free (filev[i]);
X
X  free (filev);
X}
X
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
Xint calc_sum (p, len)
X     register char *p;
X     register int len;
X{
X  register int sum;
X
X  for (sum = 0; len; len--)
X    sum += *p++;
X
X  return sum & 0xff;
X}
X
Xunsigned char *get_ptr;
X#define setup_get(PTR) get_ptr = (unsigned char*)(PTR)
X#define get_byte() (*get_ptr++)
X#define put_ptr	get_ptr
X#define setup_put(PTR) put_ptr = (unsigned char*)(PTR)
X#define put_byte(c) *put_ptr++ = (unsigned char)(c)
X
Xunsigned short get_word ()
X{
X  int b0, b1;
X
X  b0 = get_byte ();
X  b1 = get_byte ();
X  return (b1 << 8) + b0;
X}
X
Xput_word (v)
X     unsigned int	v;
X{
X  put_byte (v);
X  put_byte (v >> 8);
X}
X
Xlong get_longword ()
X{
X  long b0, b1, b2, b3;
X
X  b0 = get_byte ();
X  b1 = get_byte ();
X  b2 = get_byte ();
X  b3 = get_byte ();
X  return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
X}
X
Xput_longword (v)
X     long v;
X{
X  put_byte (v);
X  put_byte (v >> 8);
X  put_byte (v >> 16);
X  put_byte (v >> 24);
X}
X
X
Xmsdos_to_unix_filename (name, len)
X     register char *name;
X     register int len;
X{
X  register int i;
X
X#ifdef MULTIBYTE_CHAR
X  for (i = 0; i < len; i ++)
X    {
X      if (MULTIBYTE_FIRST_P (name[i]) &&
X	  MULTIBYTE_SECOND_P (name[i+1]))
X        i ++;
X#ifndef MSDOS
X      else if (name[i] == '\\')
X        name[i] = '/';
X#endif
X      else if (isupper (name[i]))
X	name[i] = tolower (name[i]);
X    }
X#else
X  for (i = 0; i < len; i ++)
X    {
X#ifndef MSDOS
X      if (name[i] == '\\')
X	name[i] = '/';
X      else
X#endif
X        if (isupper (name[i]))
X          name[i] = tolower (name[i]);
X    }
X#endif
X}
X
Xgeneric_to_unix_filename (name, len)
X     register char *name;
X     register int len;
X{
X  register int i;
X  boolean	lower_case_used = keepcase;
X
X#ifdef MULTIBYTE_CHAR
X  for (i = 0; i < len; i ++)
X    {
X      if (MULTIBYTE_FIRST_P (name[i]) &&
X	  MULTIBYTE_SECOND_P (name[i+1]))
X	i ++;
X      else if (islower (name[i]))
X	{
X	  lower_case_used = TRUE;
X	  break;
X	}
X    }
X  for (i = 0; i < len; i ++)
X    {
X      if (MULTIBYTE_FIRST_P (name[i]) &&
X	  MULTIBYTE_SECOND_P (name[i+1]))
X        i ++;
X#ifndef MSDOS
X      else if (name[i] == '\\')
X        name[i] = '/';
X#endif
X      else if (!lower_case_used && isupper (name[i]))
X	name[i] = tolower (name[i]);
X    }
X#else
X  for (i = 0; i < len; i ++)
X    if (islower (name[i]))
X      {
X	lower_case_used = TRUE;
X	break;
X      }
X  for (i = 0; i < len; i ++)
X    {
X#ifndef MSDOS
X      if (name[i] == '\\')
X	name[i] = '/';
X      else
X#endif
X        if (!lower_case_used && isupper (name[i]))
X          name[i] = tolower (name[i]);
X    }
X#endif
X}
X
Xmacos_to_unix_filename (name, len)
X     register char *name;
X     register int len;
X{
X  register int i;
X
X  for (i = 0; i < len; i ++)
X    {
X      if (name[i] == ':')
X	name[i] = '/';
X      else if (name[i] == '/')
X	name[i] = ':';
X    }
X}
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*	Generic stamp format:						*/
X/*									*/
X/*	 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16		*/
X/*	|<-------- year ------->|<- month ->|<-- day -->|		*/
X/*									*/
X/*	 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0		*/
X/*	|<--- hour --->|<---- minute --->|<- second*2 ->|		*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X
Xlong gettz ()
X{
X#if	MSDOS
X   return timezone;
X#else
X#ifdef	BSD
X   struct timeval	tp;
X   struct timezone	tzp;
X   gettimeofday (&tp, &tzp);	/* specific to 4.3BSD */
X/* return (tzp.tz_minuteswest * 60 + (tzp.tz_dsttime != 0 ? 60L * 60L : 0));*/
X   return (tzp.tz_minuteswest * 60);
X#else	/* SYSV */
X   struct tm timep;
X   long dummytime;
X
X   time(&dummytime);
X   timep = *localtime(&dummytime);
X   return timep.tm_tzadj;
X#endif
X#endif
X}
X
X#ifdef NOT_USED
Xstruct tm *msdos_to_unix_stamp_tm (a)
X     long a;
X{
X  static struct tm t;
X  t.tm_sec	= ( a          & 0x1f) * 2;
X  t.tm_min	=  (a >>    5) & 0x3f;
X  t.tm_hour	=  (a >>   11) & 0x1f;
X  t.tm_mday	=  (a >>   16) & 0x1f;
X  t.tm_mon	=  (a >> 16+5) & 0x0f - 1;
X  t.tm_year	= ((a >> 16+9) & 0x7f) + 80;
X  return &t;
X}
X#endif
X
Xtime_t generic_to_unix_stamp (t)
X     long t;
X{
X  struct tm tm;
X  long longtime;
X  static unsigned int dsboy[12] =
X    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
X  unsigned long days;
X
X  tm.tm_year =  ((int)(t >> 25) & 0x7f) + 80;
X  tm.tm_mon  =  ((int)(t >> 21) & 0x0f) - 1;     /* 0..11 means Jan..Dec */
X  tm.tm_mday =  (int)(t >> 16) & 0x1f;         /* 1..31 means 1st,...31st */
X
X  tm.tm_hour =  ((int)t >> 11) & 0x1f;
X  tm.tm_min  =  ((int)t >> 5)  & 0x3f;
X  tm.tm_sec  =  ((int)t        & 0x1f) * 2;
X
X#ifdef MSDOS
X  longtime = mktime(&tm);
X#else
X                                      /* Calculate days since 1970.01.01 */
X  days = (365 * (tm.tm_year - 70) +   /* days due to whole years */
X          (tm.tm_year - 70 + 1) / 4 + /* days due to leap years */
X          dsboy[tm.tm_mon] +          /* days since beginning of this year */
X          tm.tm_mday-1);              /* days since beginning of month */
X
X  if ((tm.tm_year % 4 == 0) &&
X      (tm.tm_year % 400 != 0) &&
X      (tm.tm_mon >= 2))         /* if this is a leap year and month */
X    days++;			/* is March or later, add a day */
X
X  /* Knowing the days, we can find seconds */
X  longtime = (((days * 24) + tm.tm_hour) * 60 + tm.tm_min) * 60 + tm.tm_sec;
X  longtime += gettz ();      /* adjust for timezone */
X#endif
X
X  /* special case:  if MSDOS format date and time were zero, then we set
X     time to be zero here too. */
X  if (t == 0)
X    longtime = 0;
X
X  /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
X  return (time_t)longtime;
X}
X
Xlong unix_to_generic_stamp (t)
X     time_t t;
X{
X  struct tm *tm = localtime (&t);
X  unsigned long stamp;
X
X  stamp =  ( ((long)(tm->tm_year - 80)) << 25 );
X  stamp += ( ((long)(tm->tm_mon + 1))   << 21 );
X  stamp += ( ((long)(tm->tm_mday))      << 16 );
X  stamp += ( ((long)(tm->tm_hour))      << 11 );
X  stamp += ( ((long)(tm->tm_min))       << 5 );
X  stamp += ( ((long)(tm->tm_sec))       >> 1 );
X
X  return stamp;
X}
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
Xboolean get_header (fp, hdr)
X     FILE *fp;
X     register LzHeader *hdr;
X{
X  int		header_size;
X  int		name_length;
X  char		data[LZHEADER_STRAGE];
X  int		checksum;
X  int		i;
X
X  bzero ((char *)hdr, sizeof (LzHeader));
X
X  if (((header_size = getc (fp)) == EOF) || (header_size == 0))
X    {
X      return FALSE;		/* finish */
X    }
X
X  if (fread (data + I_HEADER_CHECKSUM,
X		  sizeof (char), header_size + 1, fp) < header_size + 1)
X    {
X      error ("Invalid header (LHarc file ?)\a");
X      return FALSE;		/* finish */
X    }
X
X  setup_get (data + I_HEADER_CHECKSUM);
X  checksum = calc_sum (data + I_METHOD, header_size);
X  if (get_byte () != checksum)
X    warning ("Checksum error (LHarc file?)\a");
X
X  hdr->header_size = header_size;
X  bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
X#ifdef OLD
X  if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) &&
X      (bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) &&
X      (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) &&
X      (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0))
X    {
X      warning ("Unknown method (LHarc file ?)");
X      return FALSE;		/* invalid method */
X    }
X#endif
X  setup_get (data + I_PACKED_SIZE);
X  hdr->packed_size	= get_longword ();
X  hdr->original_size	= get_longword ();
X  hdr->last_modified_stamp = get_longword ();
X  hdr->attribute	= get_word ();
X  name_length		= get_byte ();
X  for (i = 0; i < name_length; i ++)
X    hdr->name[i] =(char)get_byte ();
X  hdr->name[name_length] = '\0';
X
X  /* defaults for other type */
X  hdr->unix_mode	= UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
X  hdr->unix_gid 	= 0;
X  hdr->unix_uid		= 0;
X
X  if (header_size - name_length >= 24)
X    {				/* EXTEND FORMAT */
X      hdr->crc				= get_word ();
X      hdr->extend_type			= get_byte ();
X      hdr->minor_version		= get_byte ();
X      hdr->has_crc = TRUE;
X    }
X  else if (header_size - name_length == 22)
X    {				/* Generic with CRC */
X      hdr->crc				= get_word ();
X      hdr->extend_type			= EXTEND_GENERIC;
X      hdr->has_crc = TRUE;
X    }
X  else if (header_size - name_length == 20)
X    {				/* Generic no CRC */
X      hdr->extend_type			= EXTEND_GENERIC;
X      hdr->has_crc = FALSE;
X    }
X  else
X    {
X      warning ("Unknown header (LHarc file ?)");
X      return FALSE;
X    }
X
X  switch (hdr->extend_type)
X    {
X    case EXTEND_MSDOS:
X      msdos_to_unix_filename (hdr->name, name_length);
X      hdr->unix_last_modified_stamp	=
X	generic_to_unix_stamp (hdr->last_modified_stamp);
X      break;
X
X    case EXTEND_UNIX:
X      hdr->unix_last_modified_stamp	= (time_t)get_longword ();
X      hdr->unix_mode			= get_word ();
X      hdr->unix_uid			= get_word ();
X      hdr->unix_gid			= get_word ();
X      break;
X
X    case EXTEND_MACOS:
X      macos_to_unix_filename (hdr->name, name_length);
X      hdr->unix_last_modified_stamp	=
X	generic_to_unix_stamp (hdr->last_modified_stamp);
X      break;
X
X    default:
X      generic_to_unix_filename (hdr->name, name_length);
X      hdr->unix_last_modified_stamp	=
X	generic_to_unix_stamp (hdr->last_modified_stamp);
X    }
X
X  return TRUE;
X}
X
Xinit_header (name, v_stat, hdr)
X     char *name;
X     struct stat *v_stat;
X     LzHeader *hdr;
X{
X  bcopy (LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
X  hdr->packed_size		= 0;
X  hdr->original_size		= v_stat->st_size;
X  hdr->last_modified_stamp      = unix_to_generic_stamp (v_stat->st_mtime);
X#ifdef MSDOS
X  getfilemode(name, &(hdr->attribute));
X#else
X  hdr->attribute                = GENERIC_ATTRIBUTE;
X#endif
X  strcpy (hdr->name, name);
X  hdr->crc			= 0x0000;
X  hdr->extend_type              = OUR_EXTEND;
X  hdr->unix_last_modified_stamp	= v_stat->st_mtime;
X				/* 00:00:00 since JAN.1.1970 */
X#ifdef NOT_COMPATIBLE_MODE
X  hdr->unix_mode		= v_stat->st_mode;
X#else
X  hdr->unix_mode		= v_stat->st_mode;
X#endif
X
X  hdr->unix_uid			= v_stat->st_uid;
X  hdr->unix_gid			= v_stat->st_gid;
X
X  if ((v_stat->st_mode & S_IFMT) == S_IFDIR)
X    {
X      bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
X      hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
X      hdr->original_size = 0;
X      strcat (hdr->name, "/");
X    }
X}
X
X/* Write only unix extended header. */
Xwrite_header (nafp, hdr)
X     FILE *nafp;
X     LzHeader *hdr;
X{
X  int		header_size;
X  int		name_length;
X  char          data[LZHEADER_STRAGE], *ptr;
X  int           cnt;
X
X  bzero (data, LZHEADER_STRAGE);
X  bcopy (hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
X  setup_put (data + I_PACKED_SIZE);
X  put_longword (hdr->packed_size);
X  put_longword (hdr->original_size);
X  put_longword (hdr->last_modified_stamp);
X  put_word (hdr->attribute);
X  
X#ifdef STRICT
X
X  if ( hdr->name[1] == ':' )
X  {
X    name_length = strlen(hdr->name + 2);
X    put_byte (name_length);
X    bcopy (hdr->name + 2, data + I_NAME, name_length);
X  }
X  else
X  {
X    name_length = strlen(hdr->name);
X    put_byte (name_length);
X    bcopy (hdr->name, data + I_NAME, name_length);
X  }
X  
X  for ( ptr = data + I_NAME, cnt = 0; cnt < name_length; ptr++, cnt++ )
X  {
X/*    *ptr = toupper(*ptr); */
X
X    if ( *ptr == '/' )
X      *ptr = '\\';
X  }
X#else
X  name_length = strlen (hdr->name);
X  put_byte (name_length);
X  bcopy (hdr->name, data + I_NAME, name_length);
X#endif
X  
X  setup_put (data + I_NAME + name_length);
X  put_word (hdr->crc);
X#ifdef STRICT
X  header_size = I_EXTEND_TYPE - 2 + name_length;
X#else
X  put_byte (OUR_EXTEND);
X  put_byte (CURRENT_UNIX_MINOR_VERSION);
X  put_longword ((long)hdr->unix_last_modified_stamp);
X  put_word (hdr->unix_mode);
X  put_word (hdr->unix_uid);
X  put_word (hdr->unix_gid);
X  header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
X#endif
X  data[I_HEADER_SIZE] = header_size;
X  data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
X
X  if (fwrite (data, sizeof (char), header_size + 2, nafp) == 0)
X    error ("cannot write to temporary file");
X}
X
Xboolean archive_is_msdos_sfx1 (name)
X     char *name;
X{
X  int	len = strlen (name);
X  return ((len >= 4) &&
X	  (strcmp (name + len - 4, ".com") == 0 ||
X	   strcmp (name + len - 4, ".exe") == 0));
X}
X
Xboolean skip_msdos_sfx1_code (fp)
X     FILE *fp;
X{
X  unsigned char buffer[2048];
X  unsigned char *p, *q;
X  int	n;
X
X  n = fread (buffer, sizeof (char), 2048, fp);
X
X  for (p = buffer + 2, q = buffer + n - 5; p < q; p ++)
X    {
X      /* found "-l??-" keyword (as METHOD type string) */
X      if (p[0] == '-' && p[1] == 'l' && p[4] == '-')
X	{
X	  /* size and checksum validate check */
X	  if (p[-2] > 20 && p[-1] == calc_sum (p, p[-2]))
X	    {
X              fseek (fp, (long) ((p - 2) - buffer) - n, SEEK_CUR);
X	      return TRUE;
X	    }
X	}
X    }
X
X  fseek (fp, (long) -n, SEEK_CUR);
X  return FALSE;
X}
X
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
Xmake_tmp_name (original, name)
X     char *original;
X     char *name;
X{
X#ifdef TMP_FILENAME_TEMPLATE
X  /* "/tmp/lhXXXXXX" etc. */
X  strcpy (name, TMP_FILENAME_TEMPLATE);
X#else
X  char *p, *s;
X
X  strcpy (name, original);
X  for (p = name, s = (char*)0; *p; p++)
X    if (*p == '/' || *p == '\\')
X      s = p;
X
X  strcpy ((s ? s+1 : name), "lhXXXXXX");
X#endif
X
X  mktemp (name);
X}
X
Xmake_backup_name (name, orginal)
X     char *name;
X     char *orginal;
X{
X  register char *p, *dot;
X
X  strcpy (name, orginal);
X  for (p = name, dot = (char*)0; *p; p ++)
X    {
X      if (*p == '.')
X	dot = p;
X      else if (*p == '/' || *p == '\\')
X	dot = (char*)0;
X    }
X
X  if (dot)
X    p = dot;
X
X#ifdef BACKUPNAME_EXTENTION
X  strcpy (p, BACKUPNAME_EXTENTION)
X#else
X  strcpy (p, ".bak");
X#endif
X}
X
Xmake_standard_archive_name (name, orginal)
X     char *name;
X     char *orginal;
X{
X  register char *p, *dot;
X
X  strcpy (name, orginal);
X  for (p = name, dot = (char*)0; *p; p ++)
X    {
X      if (*p == '.')
X	dot = p;
X      else if (*p == '/' || *p == '\\')
X	dot = (char*)0;
X    }
X
X  if (dot)
X    p = dot;
X
X#ifdef ARCHIVENAME_EXTENTION
X  strcpy (p, ARCHIVENAME_EXTENTION);
X#else
X  strcpy (p, ".lzh");
X#endif
X}
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X
Xboolean need_file (name)
X     char *name;
X{
X  int	i;
X
X  if (cmd_filec == 0)
X    return TRUE;
X
X  for (i = 0; i < cmd_filec; i ++)
X    {
X      if (STRING_COMPARE (cmd_filev[i], name) == 0)
X	return TRUE;
X    }
X
X  return FALSE;
X}
X
XFILE *xfopen (name, mode)
X     char *name, *mode;
X{
X  FILE *fp;
X
X  if ((fp = fopen (name, mode)) == NULL)
X    error (name);
X
X  return fp;
X}
X
X
X/*----------------------------------------------------------------------*/
X/*		Listing Stuff						*/
X/*----------------------------------------------------------------------*/
X
X/* need 14 or 22 (when long_format_listing is TRUE) column spaces */
Xprint_size (packed_size, original_size)
X     long packed_size, original_size;
X{
X  if (long_format_listing)
X    printf ("%7ld ", packed_size);
X
X  printf ("%7ld ", original_size);
X
X  if (original_size == 0L)
X    printf ("******");
X  else
X    printf ("%3d.%1d%%",
X	    (int)((packed_size * 100L) / original_size),
X	    (int)((packed_size * 1000L) / original_size) % 10);
X}
X
X/* need 12 or 17 (when long_format_listing is TRUE) column spaces */
Xprint_stamp (t)
X     time_t t;
X{
X  static boolean	got_now = FALSE;
X  static time_t		now;
X  static unsigned int	threshold;
X  static char   t_month[12*3+1] = "JanFebMarAprMayJunJulAugSepOctNovDec";
X  struct tm		*p;
X
X  if (t == 0)
X    {
X      if (long_format_listing)
X	printf ("                 "); /* 17 spaces */
X      else
X	printf ("            ");	/* 12 spaces */
X
X      return;
X    }
X
X  if (!got_now)
X    {
X      time (&now);
X      p = localtime (&now);
X      threshold = p->tm_year * 12 + p->tm_mon - 6;
X      got_now = TRUE;
X    }
X
X  p = localtime (&t);
X
X  if (long_format_listing)
X    printf ("%.3s %2d %02d:%02d %04d",
X	    &t_month[p->tm_mon * 3], p->tm_mday,
X	    p->tm_hour, p->tm_min, p->tm_year + 1900);
X  else
X    if (p->tm_year * 12 + p->tm_mon > threshold)
X      printf ("%.3s %2d %02d:%02d",
X	      &t_month[p->tm_mon * 3], p->tm_mday, p->tm_hour, p->tm_min);
X    else
X      printf ("%.3s %2d  %04d",
X	      &t_month[p->tm_mon * 3], p->tm_mday, p->tm_year + 1900);
X}
X
Xprint_bar ()
X{
X  /* 17+1+(0 or 7+1)+7+1+6+1+(0 or 1+4)+(12 or 17)+1+20 */
X  /*       12345678901234567_  1234567_123456  _123456789012   1234      */
X  if (long_format_listing)
X#ifdef STRICT
X    printf ("------- ------- ------ ---- ----------------- -------------\n");
X#else
X    printf ("----------------- ------- ------- ------ ---- ----------------- -------------\n");
X#endif
X  else
X#ifdef STRICT
X    printf ("------- ------ ------------ --------------------\n");
X#else
X    printf ("----------------- ------- ------ ------------ --------------------\n");
X#endif
X}
X
X
X/*
X  view
X */
Xcmd_view ()
X{
X  FILE		*fp;
X  LzHeader	hdr;
X  register char	*p;
X  long		a_packed_size = 0L;
X  long		a_original_size = 0L;
X  int		n_files = 0;
X  struct stat	v_stat;
X
X  if ((fp = fopen (archive_name, RMODE)) == NULL)
X    if (!expand_archive_name (expanded_archive_name, archive_name))
X      error (archive_name);
X    else
X      {
X	errno = 0;
X        fp = xfopen (expanded_archive_name, RMODE);
X	archive_name = expanded_archive_name;
X      }
X
X  if (archive_is_msdos_sfx1 (archive_name))
X    {
X      skip_msdos_sfx1_code (fp);
X    }
X
X  if (!quiet)
X    {
X      /*       12345678901234567_  1234567_123456  _  123456789012  1234 */
X#ifdef STRICT
X      printf ("%s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
X#else
X      printf (" PERMSSN  UID GID %s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
X#endif
X	      long_format_listing ? " PACKED " : "", /* 8,0 */
X	      long_format_listing ? "  CRC" : "", /* 5,0 */
X	      long_format_listing ? "  " : "", /* 2,0 */
X	      long_format_listing ? "   " : ""); /* 3,0 */
X      print_bar ();
X    }
X
X  while (get_header (fp, &hdr))
X    {
X      if (need_file (hdr.name))
X	{
X	  if (hdr.extend_type == EXTEND_UNIX)
X            {
X#ifndef STRICT
X              printf ("%c%c%c%c%c%c%c%c%c%4d/%-4d",
X		  ((hdr.unix_mode & UNIX_OWNER_READ_PERM)  ? 'r' : '-'),
X		  ((hdr.unix_mode & UNIX_OWNER_WRITE_PERM) ? 'w' : '-'),
X		  ((hdr.unix_mode & UNIX_OWNER_EXEC_PERM)  ? 'x' : '-'),
X		  ((hdr.unix_mode & UNIX_GROUP_READ_PERM)  ? 'r' : '-'),
X		  ((hdr.unix_mode & UNIX_GROUP_WRITE_PERM) ? 'w' : '-'),
X		  ((hdr.unix_mode & UNIX_GROUP_EXEC_PERM)  ? 'x' : '-'),
X		  ((hdr.unix_mode & UNIX_OTHER_READ_PERM)  ? 'r' : '-'),
X		  ((hdr.unix_mode & UNIX_OTHER_WRITE_PERM) ? 'w' : '-'),
X		  ((hdr.unix_mode & UNIX_OTHER_EXEC_PERM)  ? 'x' : '-'),
X		  hdr.unix_uid, hdr.unix_gid);
X#endif
X	    }
X	  else
X	    {
X	      switch (hdr.extend_type)
X		{			/* max 18 characters */
X                case EXTEND_GENERIC:    p = "[Generic]"; break;
X
X		case EXTEND_CPM:	p = "[CP/M]"; break;
X
X		  /* OS-9 and FLEX's CPU is MC-6809. I like it. :-)  */
X		case EXTEND_FLEX:	p = "[FLEX]"; break;
X
X		case EXTEND_OS9:	p = "[OS-9]"; break;
X
X		  /* I guessed from this ID.  Is this right? */
X		case EXTEND_OS68K:	p = "[OS-9/68K]"; break;
X
X		case EXTEND_MSDOS:	p = "[MS-DOS]"; break;
X
X		  /* I have Macintosh. :-)  */
X		case EXTEND_MACOS:	p = "[Mac OS]"; break;
X
X		case EXTEND_OS2:	p = "[OS/2]"; break;
X
X		case EXTEND_HUMAN:	p = "[Human68K]"; break;
X
X		case EXTEND_OS386:	p = "[OS-386]"; break;
X
X#ifdef EXTEND_TOWNSOS
X		  /* This ID isn't fixed */
X		case EXTEND_TOWNSOS:	p = "[TownsOS]"; break;
X#endif
X
X		  /* Ouch!  Please customize it's ID.  */
X                default:                p = "[Unknown]"; break;
X                }
X#ifndef STRICT
X              printf ("%-18.18s", p);
X#endif
X	    }
X
X	  print_size (hdr.packed_size, hdr.original_size);
X
X	  if (long_format_listing)
X	    if (hdr.has_crc)
X	      printf (" %04x", hdr.crc);
X	    else
X	      printf (" ****");
X
X	  printf (" ");
X	  print_stamp (hdr.unix_last_modified_stamp);
X	  printf (" %s\n", hdr.name);
X	  n_files ++;
X	  a_packed_size += hdr.packed_size;
X	  a_original_size += hdr.original_size;
X	}
X      fseek (fp, hdr.packed_size, SEEK_CUR);
X    }
X
X  fclose (fp);
X  if (!quiet)
X    {
X      print_bar ();
X
X#ifndef STRICT
X      printf (" Total %4d file%c ",
X	      n_files, (n_files == 1) ? ' ' : 's');
X#endif
X      print_size (a_packed_size, a_original_size);
X      printf (" ");
X
X      if (long_format_listing)
X	printf ("     ");
X
X      if (stat (archive_name, &v_stat) < 0)
X	print_stamp ((time_t)0);
X      else
X	print_stamp (v_stat.st_mtime);
X
X#ifdef STRICT
X      printf (" %4d file%c ",
X	      n_files, (n_files == 1) ? ' ' : 's');
X#endif
X      printf ("\n");
X    }
X
X  return;
X}
X
X
Xboolean make_parent_path (name)
X     char *name;
X{
X  char		path[FILENAME_LENGTH];
X  struct stat	v_stat;
X  register char	*p;
X
X /* make parent directory name into PATH for recursive call */
X  strcpy (path, name);
X  for (p = path + strlen (path); p > path; p --)
X    if (p[-1] == '/' || p[-1] == '\\')
X      {
X	p[-1] = '\0';
X	break;
X      }
X
X  if (p == path)
X    return FALSE;		/* no more parent. */
X
X  if (stat (path, &v_stat) >= 0)
X    {
X      if ((v_stat.st_mode & S_IFMT) != S_IFDIR)
X	return FALSE;		/* already exist. but it isn't directory. */
X      return TRUE;		/* already exist its directory. */
X    }
X
X  errno = 0;
X
X  if (!quiet)
X    message ("Making Directory", path);
X
X  if (mkdir (path, 0777) >= 0)	/* try */
X    return TRUE;		/* successful done. */
X
X  errno = 0;
X
X  if (!make_parent_path (path))
X    return FALSE;
X
X  if (mkdir (path, 0777) < 0)		/* try again */
X    return FALSE;
X
X  return TRUE;
X}
X
XFILE *open_with_make_path (name)
X     char *name;
X{
X  FILE		*fp;
X  struct stat	v_stat;
X  char		buffer[1024];
X
X  if (stat (name, &v_stat) >= 0)
X    {
X      if ((v_stat.st_mode & S_IFMT) != S_IFREG)
X	return NULL;
X
X      if (!force)
X	{
X	  for (;;)
X	    {
X	      fprintf (stderr, "%s OverWrite ?(Yes/No/All) ", name);
X	      fflush (stderr);
X	      gets (buffer);
X	      if (buffer[0] == 'N' || buffer[0] == 'n')
X		return NULL;
X	      if (buffer[0] == 'Y' || buffer[0] == 'y')
X		break;
X	      if (buffer[0] == 'A' || buffer[0] == 'a')
X		{
X		  force = TRUE;
X		  break;
X		}
X	    }
X	}
X    }
X
X  fp = fopen (name, WMODE);
X  if (!fp)
X    {
X      errno = 0;
X      if (!make_parent_path (name))
X	return NULL;
X
X      fp = fopen (name, WMODE);
X      if (!fp)
X        message ("Error:", name);
X    }
X  return fp;
X}
X
X#ifdef MSDOS
Xvoid dosname(char *name)
X{
X  char *ptr, *first = NULL, *last = NULL;
X  char temp[8];
X
X  for ( ptr = strchr(name, 0); ptr >= name; ptr-- )
X    if ( *ptr == '.' )
X    {
X      if ( last == NULL )
X        last = ptr;
X    }
X    else if ( (*ptr == '/') || (*ptr == '\\') )
X    {
X      first = ptr + 1;
X      break;
X    }
X
X  if ( first == NULL )
X    first = name;
X  if ( last == NULL )
X    last = strchr(name, 0);
X
X  for ( ptr = first; ptr < last; ptr++ )
X    if ( *ptr == '.' )
X      *ptr = '_';
X
X  if ( strlen(last) > 4 )
X    last[4] = 0;
X
X  if ( last - first > 8 )
X  {
X    strcpy(temp, last);
X    strcpy(first + 8, last);
X  }
X}
X#endif
X
Xextern int decode_lzhuf (), decode_larc ();
Xextern int decode_stored_crc (), decode_stored_nocrc ();
X
Xextract_one (fp, hdr)
X     FILE *fp;
X     LzHeader *hdr;
X{
X  FILE		*ofp;		/* output file */
X  char		name[1024];
X  time_t	utimebuf[2];
X  int		crc;
X  int		(*decode_proc)(); /* (ifp,ofp,original_size,name) */
X  int		save_quiet;
X
X  strcpy (name, hdr->name);
X  if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
X    {
X      if (bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) == 0)
X	decode_proc = decode_lzhuf;
X      else if ((bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) == 0) ||
X	       (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) == 0))
X	decode_proc = (hdr->has_crc) ? decode_stored_crc : decode_stored_nocrc;
X      else if (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) == 0)
X	decode_proc = decode_larc;
X      else
X        message ("Error:", "Sorry, Cannot Extract this method.");
X
X      reading_filename = archive_name;
X      writting_filename = name;
X      if (output_to_stdout)
X	{
X          if (!quiet)
X            printf ("::::::::\r\n%s\r\n::::::::\r\n", name);
X
X          if ( strlen(pager) != 0 )
X            ofp = popen(pager, WMODE);
X          else
X            ofp = stdout;
X
X	  save_quiet = quiet;
X          quiet = TRUE;
X          crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
X          quiet = save_quiet;
X
X          if ( strlen(pager) != 0 )
X            pclose(ofp);
X	}
X      else if (output_to_test)
X        {
X          ofp = fopen(NULLFILE, WMODE);
X          crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
X          fclose(ofp);
X        }
X      else
X        {
X#ifdef MSDOS
X          dosname(name);
X#endif
X	  if ((ofp = open_with_make_path (name)) == NULL)
X	    return;
X	  else
X	    {
X	      crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
X	      fclose (ofp);
X	    }
X	}
X
X      if (hdr->has_crc && (crc != hdr->crc))
X        if (output_to_test)
X          message ("Error:", "CRC failed\a");
X        else
X          error ("CRC failed\a");
X    }
X  else
X    {
X      /* NAME has trailing SLASH '/', (^_^) */
X      if (!output_to_stdout &&
X	  !make_parent_path (name))
X	error (name);
X    }
X
X  if (!output_to_stdout && !output_to_test)
X    {
X      utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
X      utime (name, utimebuf);
X
X#ifdef NOT_COMPATIBLE_MODE
X      setfilemode(name, hdr->attribute);
X#else
X      chmod (name, hdr->unix_mode);
X#endif
X
X#ifndef MSDOS
X      chown (name, hdr->unix_uid, hdr->unix_gid);
X#endif
X      errno = 0;
X    }
X}
X
X
X/*
X  extract
X */
Xcmd_extract ()
X{
X  LzHeader	hdr;
X  long		pos;
X  FILE		*fp;
X
X  if ((fp = fopen (archive_name, RMODE)) == NULL)
X    if (!expand_archive_name (expanded_archive_name, archive_name))
X      error (archive_name);
X    else
X      {
X	errno = 0;
X        fp = xfopen (expanded_archive_name, RMODE);
X	archive_name = expanded_archive_name;
X      }
X
X  if (archive_is_msdos_sfx1 (archive_name))
X    {
X      skip_msdos_sfx1_code (fp);
X    }
X
X  while (get_header (fp, &hdr))
X    {
X      if (need_file (hdr.name))
X	{
X	  pos = ftell (fp);
X	  extract_one (fp, &hdr);
X	  fseek (fp, pos + hdr.packed_size, SEEK_SET);
SHAR_EOF
echo "End of part 1"
echo "File lharc.c is continued in part 2"
echo "2" > s2_seq_.tmp
exit 0
-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
    VMS is a text-only adventure game. If you win you can use unix.

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (12/06/90)

#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file lharc.c continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file lharc.c"
sed 's/^X//' << 'SHAR_EOF' >> lharc.c
X	} else {
X	  fseek (fp, hdr.packed_size, SEEK_CUR);
X	}
X    }
X
X  fclose (fp);
X
X  return;
X}
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
Xextern int encode_lzhuf ();
Xextern int encode_storerd_crc ();
X
Xappend_one (fp, nafp, hdr)
X     FILE *fp, *nafp;
X     LzHeader *hdr;
X{
X  long	header_pos, next_pos, org_pos, data_pos;
X  long	v_original_size, v_packed_size;
X
X  reading_filename = hdr->name;
X  writting_filename = temporary_name;
X
X  org_pos = ftell (fp);
X  header_pos = ftell (nafp);
X  write_header (nafp, hdr);	/* DUMMY */
X
X  if (hdr->original_size == 0)
X    {
X      printf("%s - not frozen\n",hdr->name);
X      return;		/* previous write_header is not DUMMY. (^_^) */
X    }
X
X  data_pos = ftell (nafp);
X  hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
X			   &v_original_size, &v_packed_size, hdr->name);
X  if (v_packed_size < v_original_size)
X    {
X      next_pos = ftell (nafp);
X    }
X  else
X    {				/* retry by stored method */
X      fseek (fp, org_pos, SEEK_SET);
X      fseek (nafp, data_pos, SEEK_SET);
X      hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size,
X				    &v_original_size, &v_packed_size);
X      fflush (nafp);
X      next_pos = ftell (nafp);
X      ftruncate (fileno (nafp), next_pos);
X      bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
X    }
X  hdr->original_size = v_original_size;
X  hdr->packed_size = v_packed_size;
X  fseek (nafp, header_pos, SEEK_SET);
X  write_header (nafp, hdr);
X  fseek (nafp, next_pos, SEEK_SET);
X}
X
Xwrite_tail (nafp)
X     FILE *nafp;
X{
X  putc (0x00, nafp);
X}
X
Xcopy_old_one (oafp, nafp, hdr)
X     FILE *oafp, *nafp;
X     LzHeader *hdr;
X{
X  if (noexec)
X    {
X      fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
X    }
X  else
X    {
X      reading_filename = archive_name;
X      writting_filename = temporary_name;
X      copy_file (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size);
X    }
X}
X
X
XFILE *append_it (name, oafp, nafp)
X     char *name;
X     FILE *oafp, *nafp;
X{
X  LzHeader	ahdr, hdr;
X  FILE		*fp;
X  long		old_header;
X  int		cmp;
X  int		filec;
X  char		**filev;
X  int		i;
X
X  struct stat	v_stat;
X  boolean	directory;
X
X  /* check that any added name is not the same as the archive name */
X  if (strcmp(name, archive_name) == 0) return oafp;
X
X  if (!delete_from_archive)
X    if (stat (name, &v_stat) < 0)
X      {
X        message ("Error:", name);
X        return oafp;
X      }
X
X  directory = ((v_stat.st_mode & S_IFMT) == S_IFDIR);
X
X  init_header (name, &v_stat, &hdr);
X
X  if (!delete_from_archive && !directory && !noexec)
X    fp = xfopen (name, RMODE);
X
X  while (oafp)
X    {
X      old_header = ftell (oafp);
X      if (!get_header (oafp, &ahdr))
X	{
X	  fclose (oafp);
X	  oafp = NULL;
X	  break;
X	}
X      else
X	{
X	  cmp = STRING_COMPARE (ahdr.name, hdr.name);
X	  if (cmp < 0)
X	    {		/* SKIP */
X	      fseek (oafp, old_header, SEEK_SET);
X	      copy_old_one (oafp, nafp, &ahdr);
X	    }
X	  else if (cmp == 0)
X	    {		/* REPLACE */
X	      fseek (oafp, ahdr.packed_size, SEEK_CUR);
X	      break;
X	    }
X	  else		/* cmp > 0, INSERT */
X	    {
X	      fseek (oafp, old_header, SEEK_SET);
X	      break;
X	    }
X	}
X    }
X
X  if (delete_from_archive)
X    {
X      if (noexec)
X        fprintf (stderr, "DELETE %s\n", name);
X      else
X        printf ("%s - Deleted\n", name);
X    }
X  else
X    {
X      if ( !oafp || (cmp > 0) || !update_if_newer
X           || (ahdr.unix_last_modified_stamp < hdr.unix_last_modified_stamp) )
X	{
X	  if (noexec)
X	    fprintf (stderr, "APPEND %s\n", name);
X          else
X#ifdef STRICT
X            if ( !directory )
X#endif
X              if ( !update_freshen || (cmp == 0) )
X                append_one (fp, nafp, &hdr);
X	}
X      else
X	{					/* archive has old one */
X	  fseek (oafp, old_header, SEEK_SET);
X	  copy_old_one (oafp, nafp, &ahdr);
X	}
X
X      if (!directory)
X	{
X	  if (!noexec)
X	    fclose (fp);
X	}
X      else
X	{			/* recurcive call */
X	  if (find_files (name, &filec, &filev))
X	    {
X	      for (i = 0; i < filec; i ++)
X		oafp = append_it (filev[i], oafp, nafp);
X	      free_files (filec, filev);
X	    }
X	  return oafp;
X	}
X    }
X
X  return oafp;
X}
X
X
Xremove_it (name)
X     char *name;
X{
X  struct stat	v_stat;
X  int		i;
X  char		**filev;
X  int		filec;
X
X  if (stat (name, &v_stat) < 0)
X    {
X      fprintf (stderr, "Cannot access \"%s\".\n", name);
X      return;
X    }
X
X  if ((v_stat.st_mode & S_IFMT) == S_IFDIR)
X    {
X      if (!find_files (name, &filec, &filev))
X	{
X          fprintf (stderr, "Cannot open directory \"%s\".\n", name);
X	  return;
X	}
X
X      for (i = 0; i < filec; i ++)
X	remove_it (filev[i]);
X
X      free_files (filec, filev);
X
X      if (noexec)
X        printf ("REMOVE DIR %s\n", name);
X      else if (rmdir (name) < 0)
X        fprintf (stderr, "Cannot remove directory \"%s\".\n", name);
X      else if (!quiet)
X        printf ("%s - Removed\n", name);
X    }
X  else
X    {
X      if (noexec)
X        printf ("REMOVE %s\n", name);
X      else if (unlink (name) < 0)
X        fprintf (stderr, "Cannot delete \"%s\".\n", name);
X      else if (!quiet)
X        printf ("%s - Removed\n", name);
X    }
X}
X
X#ifdef FASTCOPY
X#define BUFFER_SIZE 16384
X
X#ifndef O_BINARY
X#define O_BINARY 0
X#endif
X
Xcopy_archive(src, dst)
Xchar *src;
Xchar *dst;
X{
X  int ih, oh;
X  unsigned chunk;
X  char *buffer = (char *) rson;
X
X  printf ("Copying temp to archive ... ");
X
X  ih = open (src, O_RDONLY | O_BINARY);
X  if ( ih == -1 )
X    error(src);
X  oh = open (dst, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
X  if ( oh == -1 )
X    error(dst);
X
X  while ( (chunk = read(ih, buffer, BUFFER_SIZE)) > 0 )
X    if ( write(oh, buffer, chunk) != chunk )
X      error(dst);
X
X  close (ih);
X  close (oh);
X
X  printf("\b\b\b\b   \b\b\b\b.\n");
X}
X#endif
X
Xcmd_append ()
X{
X  LzHeader	ahdr;
X  FILE		*oafp, *nafp;
X  char		backup_archive_name [ FILENAME_LENGTH ];
X  char		new_archive_name_buffer [ FILENAME_LENGTH ];
X  char		*new_archive_name;
X  int		i;
X  long		old_header;
X  struct stat	v_stat;
X  boolean	old_archive_exist;
X
X  if (cmd_filec == 0)
X    return;
X
X  make_tmp_name (archive_name, temporary_name);
X
X  if ((oafp = fopen (archive_name, RMODE)) == NULL)
X    if (expand_archive_name (expanded_archive_name, archive_name))
X      {
X	errno = 0;
X        oafp = fopen (expanded_archive_name, RMODE);
X	archive_name = expanded_archive_name;
X      }
X
X  old_archive_exist = (oafp) ? TRUE : FALSE;
X  if (new_archive && oafp)
X    {
X      fclose (oafp);
X      oafp = NULL;
X    }
X
X  if (oafp && archive_is_msdos_sfx1 (archive_name))
X    {
X      skip_msdos_sfx1_code (oafp);
X      make_standard_archive_name (new_archive_name_buffer, archive_name);
X      new_archive_name = new_archive_name_buffer;
X    }
X  else
X    {
X      new_archive_name = archive_name;
X    }
X
X  errno = 0;
X  if (!noexec)
X    {
X      nafp = xfopen (temporary_name, WMODE);
X      remove_temporary_at_error = TRUE;
X    }
X
X  for (i = 0; i < cmd_filec; i ++)
X    oafp = append_it (cmd_filev[i], oafp, nafp);
X
X  if (oafp)
X    {
X      old_header = ftell (oafp);
X      while (get_header (oafp, &ahdr))
X	{
X	  fseek (oafp, old_header, SEEK_SET);
X	  copy_old_one (oafp, nafp, &ahdr);
X	  old_header = ftell (oafp);
X	}
X      fclose (oafp);
X    }
X
X  if (!noexec)
X    {
X      write_tail (nafp);
X      fclose (nafp);
X    }
X
X  make_backup_name (backup_archive_name, archive_name);
X
X  if (!noexec && old_archive_exist)
X  {
X    unlink(backup_archive_name);
X
X    if (rename (archive_name, backup_archive_name) < 0)
X      error (archive_name);
X  }
X
X  if (!quiet && new_archive_name == new_archive_name_buffer)
X    {				/* warning at old archive is SFX */
X      printf ("New Archive File is \"%s\"\n", new_archive_name);
X    }
X
X  if (!noexec && rename (temporary_name, new_archive_name) < 0)
X    {
X      if (stat (temporary_name, &v_stat) < 0)
X	error (temporary_name);
X
X#ifdef FASTCOPY
X      copy_archive(temporary_name, archive_name);
X#else
X      oafp = xfopen (temporary_name, RMODE);
X      nafp = xfopen (archive_name, WMODE);
X      reading_filename = temporary_name;
X      writting_filename = archive_name;
X      copy_file (oafp, nafp, (long)v_stat.st_size);
X      fclose (nafp);
X      fclose (oafp);
X#endif
X
X      unlink (temporary_name);
X    }
X  remove_temporary_at_error = FALSE;
X
X  if (delete_after_append)
X    {
X      if (!quiet && !noexec)
X	printf ("Erasing...\n");
X      for (i = 0; i < cmd_filec; i ++)
X	remove_it (cmd_filev[i]);
X    }
X
X  return;
X}
X
X/* XENIX kludges */
X#ifdef M_XENIX
Xrename(old, new)
Xchar *old, *new;
X{
X    char cmd[256];
X
X    sprintf(cmd, "/bin/mv %s %s", old, new);
X    system(cmd);
X}
X#endif	/* XENIX */
SHAR_EOF
echo "File lharc.c is complete"
chmod 0666 lharc.c || echo "restore of lharc.c fails"
echo "x - extracting lharc.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > lharc.doc &&
X------------------------------------------------------------------------------
X		    LHarc UNIX  Release #3  V0.03 beta version
X			Copyright (C) 1989  Yooichi.Tagawa
X
X						cl mj
X						zoMIX ID: y.tagawa
X------------------------------------------------------------------------------
X	1Lv
X
X	UNIX EL LHarc p
X
X
X	H	:AAIfgH"),hAUNIX E LHarc (LHarc UNIX) p LHarc F
X	*5\7B
X
X
Xyg"{z
X	lharc {axevludmcp}[qnft] archive_file [files or directories...]
X
X	R}hMAaxevludmcp L"Cj)PFBpwh5\7B(H*s	B)
X	IvVM qnft )gp"-BE`wh	B\E7B
X	(H*	B\B3
X
X
XyA[JCut@C<z
X	wh5=t@C<Lt@C*H/jNA.lzh pt@C<LckIt
X		A5D5\7B5=*AD;Lj
X	AIKhM h\9q*A	^pcATtBbNXF5D .lzh Ij7
X	iL*G")F]\5")Fv"\7B
X	.com (fQ .exe LTbtBNXLj
X	3j= SFX ().W
X	5\7B5)5ALHarc UNIX EMASFX `.Lt@Cp
X	ME+\9qBSFX `.LA[JCut@CIN5DG	A/
X	=j
X	
X
X
XyR}hjz
X    a		A[JCut@CIwh5=t@CpG	A
X		fBNg
X		WD
X    x \=M e	A[JCut@CL)gwh5=t@C)7WDLt@
X		Cp
X    v \=M l	A[JCut@C`I
X		WDLt@CLjp\&5\7Bl Lj
X		qpoM5\7B
X    u		wh5=t@C*A[JCut@C`I
X		CfhV5")AA[JCut@C`I
X		jN
X    d		A[JCut@CL)gwh5=t@Cp
X    m		A[JCut@CIwh5=t@Cp
X		5=t@Cp
X    c		A[JCut@CL`epj
X		p
X    p		A[JCut@CL)gwh5=t@C)7WDL`e
X		pW
X
XyIvVjz
X    q		bZ[WL}'p
X    n		@
X    f		
X    t		eLXg[hBMS-DOS EELeLXgt@CL	|
X		O
X		dl*Omi)`5j\9qB)
X
X
Xy]
X	MS-DOS LHarc V1.13c ( i"MA;jHO) E
X	CF]
X	Z[W*oi)`5j\9qB
X	LHarc UNIX E
X	h*
X
X
XyzzKhz
X	H	:LpEA
X
X	1.  
X	2.  zz`eIB"DMA
X	    a.  zzL
X		v
X		
X		gppS7i1FB
X	    b.  LHarc IN7it	A	?l*t/gjD
X		jg`E+i>/
X		t	A	?l*t/gjD"i1Fp>&5=hLgppS
X		7i1FB
X	    c.  oCi
X	3.  
X	4.  1Lv
X	    X5H"B
X	5.  
X	    	mH"B
X	6.  1Lv
X	    p5D`)\mH"B1Lj
X	    H-ALHarc F<fADM"/H"B
X	7.  $pI
X	    F_iB
X	    a.	1Lv
X	    b.	$pL
X		=j
X	    c.	CXg[LhiF5Dgp7ij
X		$1Fp
X		\=A;LF+L9
X	    d.	$ppt	A	?lF5D
X		$pRMA;LT|[gp
X
X
Xy
X	LZHUF @L
X	;jp Nifty IP	n5A\=ALArc L
X	1jgLvv)g LZHUF @yQAMS-DOS E LHarc p
X	A
X	N
X	qI
X
X
X
XGL V0.03:
X    *	1.  quiet F text_mode LIvVpt/D]\5=B
X	    text_mode LIvVMAdl*Omi)`5j\9qLE
X	    5DgAD->3"B
X	2.  G	[bZ[W*sKXH* i)`5j\9qB
X    +	3.  
X	    1qH`qE""LE5e$)B(^_^)
X    +	4.  TufBNg
X	    A[JCut@CIG	ALbhpFhL<-1F*E+\5=B
X    *	5.  3k/W
X	    E7B LArc type 4 yQAtype 5 I`N	5\5=B
X    *	6.  MS-DOS ELZtGNXg	NgLA[JCu`.`	p
X	    $I5\5=B
X	7.  MS-DOS E V1.13c LA[JCut@C* [MS-DOS] EH-A
X	    [generic] IHh\7*AMS-DOS ELLE =h(\*))gM
X	    [MS-DOS] FF/E+itH[}bgIHAD"iFv"\7B(^_^)
X	8.  MS-DOS E V1.13c ELTufBNg
X	    W
X	9.  {M VAX 11/785 UNIX 4.2BSD E
X	    (`FbNRj* i)`5j\9q)
X    +	10. d66)Fv"\7*AMS-DOS <--> UNIX 
X	    L]MoCi
X    *	11. System-V VLZApeUI
X    *	12. v F l R}hL\&`TLO
X    *	13. lzhuf.c )g @mK6pMT+\5=B(Fv$)
X
XGL V0.02:
X	1.  verbose/quiet/text_mode option M\>"E7B
X	2.  G	[bZ[W*sKXH* i)`5j\9qB
X    *	3.  
X	    1qH`qE""LE5e$)B(^_^)
X    *	4.  TufBNg
X	    A[JCut@CIG	ALbhpFhL<-1F*E+\5=B
X	5.  3k/W
X	    >Fv"\7B
X	6.  ;
X	    5D"\9qB
X	7.  MS-DOS E V1.13c LA[JCut@C* [MS-DOS] EH-A
X	    [generic] IHh\7*AMS-DOS ELLE =h(\*))gM
X	    [MS-DOS] FF/E+itH[}bgIHAD"iFv"\7B(^_^)
X	8.  MS-DOS E V1.13c ELTufBNg
X	    W
X	9.  {M vax 11/785 UNIX 4.2BSD E
X	    (`FbNRj* i)`5j\9q)
X    *	10. d66)Fv"\7*AMS-DOS <--> UNIX 
X	    L]MoCi
X
XGL V0.01:
X	1.  verbose/quiet/text_mode option M\>"E7B
X	2.  G	[bZ[W*sKXH* i)`5j\9qB
X	3.  
X	4.  TufBNg
X	5.  3k/W
X	    >Fv"\7B
X	6.  ;
X	    5D"\9qB
X	7.  MS-DOS E V1.13c LA[JCut@C* [MS-DOS] EH-A
X	    [generic] IHh\7*AMS-DOS ELLE =h(\*))gM
X	    [MS-DOS] FF/E+itH[}bgIHAD"iFv"\7B(^_^)
X	8.  MS-DOS E V1.13c ELTufBNg
X	    W
X	9.  {M vax 11/785 UNIX 4.2BSD E
X	    (`FbNRj* i)`5j\9q)
X
X
X------------------------------------------------------------------------------
SHAR_EOF
chmod 0666 lharc.doc || echo "restore of lharc.doc fails"
echo "x - extracting lhdir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > lhdir.c &&
X/*----------------------------------------------------------------------*/
X/*		Directory access routine for LHarc UNIX			*/
X/*									*/
X/*		Copyright(C) MCMLXXXIX  Yooichi.Tagawa			*/
X/*									*/
X/*	Emulate opendir(),readdir(),closedir() function for LHarc	*/
X/*									*/
X/*  V0.00  Original				1988.05.31  Y.Tagawa	*/
X/*  V0.03  Release #3 for LHarc UNIX		1988.07.02  Y.Tagawa	*/
X/*----------------------------------------------------------------------*/
X
X
X#include <sys/types.h>
X
X/* Where is O_RDONLY ? (^_^) */
X#include <sys/file.h>
X#ifndef O_RDONLY
X#include <fcntl.h>
X#endif
X
X#define direct old_direct
X#include <sys/dir.h>
X#undef direct
X
X#include "lhdir.h"
X
XDIR *opendir (name)
X     char *name;
X{
X  register DIR *dirp;
X  register int fd;
X  if ((fd = open (name, O_RDONLY)) >= 0)
X    {
X      if ((dirp = (DIR*)malloc (sizeof (DIR))) != (DIR*)0)
X	{
X	  dirp->dd_fd = fd;
X	  dirp->dd_loc = 0;
X	  dirp->dd_size = 0;
X	  return dirp;
X	}
X
X      close (fd);
X    }
X
X  return (DIR*)0;
X}
X
Xstruct direct *readdir (dirp)
X     register DIR *dirp;
X{
X  static struct direct lhdir;
X  register struct old_direct *dp;
X
X  do {
X    if (dirp->dd_loc >= dirp->dd_size)
X      {
X	dirp->dd_loc = 0;
X	if ((dirp->dd_size = read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
X	  return (struct direct *)0;
X      }
X
X    dp = (struct old_direct *)(dirp->dd_buf + dirp->dd_loc);
X
X    if (dirp->dd_loc + sizeof (struct old_direct) > dirp->dd_size)
X      return (struct direct *)0;
X
X    dirp->dd_loc += sizeof (struct old_direct);
X
X  } while (dp->d_ino == 0) ;
X
X  /* construct new format */
X  lhdir.d_ino = dp->d_ino;
X  strncpy (lhdir.d_name, dp->d_name, DIRSIZ);
X  lhdir.d_name[DIRSIZ] = '\0';
X  lhdir.d_namlen = strlen (lhdir.d_name);
X
X  return &lhdir;
X}
X
Xclosedir (dirp)
X     DIR *dirp;
X{
X  close (dirp->dd_fd);
X  free (dirp);
X}
X
SHAR_EOF
chmod 0600 lhdir.c || echo "restore of lhdir.c fails"
echo "x - extracting lhdir.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > lhdir.h &&
X/*----------------------------------------------------------------------*/
X/*		Directory access routine for LHarc UNIX			*/
X/*									*/
X/*		Copyright(C) MCMLXXXIX  Yooichi.Tagawa			*/
X/*	Emulate opendir(),readdir(),closedir() function for LHarc	*/
X/*									*/
X/*  V0.00  Original				1988.05.31  Y.Tagawa	*/
X/*  V0.03  Release #3 for LHarc UNIX		1988.07.02  Y.Tagawa	*/
X/*----------------------------------------------------------------------*/
X
X
X/* DIRBLKSIZ must be sizeof (SYSTEM struct direct) * N   !!! */
X
X#ifndef DIRBLKSIZ
X#define DIRBLKSIZ	512
X#endif
X
Xstruct direct {
X  int	d_ino;
X  int	d_namlen;
X  char	d_name[256];
X};
X
Xtypedef struct {
X  int	dd_fd;
X  int	dd_loc;
X  int	dd_size;
X  char	dd_buf[DIRBLKSIZ];
X} DIR;
X
X
Xextern DIR *opendir ();
Xextern struct direct *readdir ();
Xextern closedir ();
X
SHAR_EOF
chmod 0600 lhdir.h || echo "restore of lhdir.h fails"
echo "x - extracting lhio.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > lhio.c &&
X/*----------------------------------------------------------------------*/
X/*		File I/O module for LHarc UNIX				*/
X/*									*/
X/*		Copyright(C) MCMLXXXIX  Yooichi.Tagawa			*/
X/*									*/
X/*  V0.00  Original				1989.06.25  Y.Tagawa	*/
X/*  V0.03  Release #3  Beta Version		1989.07.02  Y.Tagawa	*/
X/*  V0.03a Fix few bugs				1989.07.04  Y.Tagawa	*/
X/*----------------------------------------------------------------------*/
X
X#include <stdio.h>
X#include "lhio.h"
X
X#ifndef BUFFER_SIZE
X#define BUFFER_SIZE	16384
X#endif
X
X
Xextern int	text_mode;			/* in lharc.c */
XFILE            *crc_infile, *crc_outfile;      /* in lzhuf.c */
X
Xextern int rson[];
X
X/* These functions are NO-RETURN */
Xextern read_error ();
Xextern write_error ();
X
X
Xint		crc_getc_cashe;
Xunsigned int	crc_value;
Xunsigned int	crc_table[0x100];
Xlong		crc_size;
X
X
Xcrcsub (ptr, length)
X     char		*ptr;
X     register int	length;
X{
X  register unsigned char	*p;
X  register unsigned int		ctmp;
X
X  if (length != 0)
X    {
X      ctmp = crc_value;
X      p = (unsigned char*)ptr;
X      for (; length; length --)
X	{
X	  ctmp ^= (unsigned int)*p++;
X	  ctmp = (ctmp >> 8) ^ crc_table [ ctmp & 0xff ];
X	}
X      crc_value = ctmp;
X    }
X}
X
X#ifndef __GNUC__
Xvoid putc_crc (c)
X     int c;
X{
X  CRC_CHAR (c);
X  if (!text_mode || (c != 0x0d && c != 0x1a))
X    {
X      putc (c, crc_outfile);
X    }
X}
X
Xint getc_crc ()
X{
X  int	c;
X
X  if (crc_getc_cashe != EOF)
X    {
X      c = crc_getc_cashe;
X      crc_getc_cashe = EOF;
X      CRC_CHAR (c);
X      crc_size++;
X    }
X  else if ((c = getc (crc_infile)) != EOF)
X    {
X      if (text_mode && c == 0x0a)
X	{
X	  crc_getc_cashe = c;
X	  c = 0x0d;
X	}
X      CRC_CHAR (c);
X      crc_size++;
X    }
X  return c;
X}
X#endif
X
X
X
Xinit_crc ()
X{
X  static int		inited = 0;
X  register unsigned int	*p = crc_table;
X  register int		i, j;
X  register unsigned int	x;
X
X  if (!inited) {
X    for (j = 0; j < 256; j ++) {
X      x = j;
X      for (i = 0; i < 8; i ++) {
X	if ((x & 1) != 0) {
X	  x = (x >> 1) ^ 0xa001;
X	} else {
X	  x = (x >> 1);
X	}
X      }
X      *p ++ = x;
X    }
X    inited = 1;
X  }
X  crc_value = 0;
X  crc_getc_cashe = EOF;
X  crc_size = 0;
X}
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X/* if return value is -1, see errno */
Xcopy_binary_file (ifp, ofp, size, crc_flag)
X     FILE	*ifp, *ofp;
X     long	size;
X     int	crc_flag;	/* as boolean value */
X{
X  char *buffer = (char *) rson;
X  int read_size;
X  int n;
X
X  /* safty */
X  fflush (ofp);
X
X  while (size > 0)
X    {
X      read_size = ((size < (long)BUFFER_SIZE) ? (int)size : BUFFER_SIZE);
X
X      n = fread (buffer, sizeof (char), read_size, ifp);
X
X      if (n == 0)
X	read_error ();
X
X      if (fwrite (buffer, sizeof (char), n, ofp) < n)
X	write_error ();
X
X      if (crc_flag)
X	crcsub (buffer, n);
X
X      size -= (long)n;
X    }
X}
X
X/* read UNIX text file '0A' and write generic text file '0D0A' */
Xwrite_generic_text_file (ifp, ofp, size)
X     FILE	*ifp, *ofp;
X     long	size;
X{
X  char		buffer[BUFFER_SIZE];
X  int		read_size, write_count, n, m;
X  register char	*p, *p1, *e;
X
X  /* safty */
X  fflush (ofp);
X
X  write_count = 0;
X
X  while (size > 0)
X    {
X      read_size = ((size < BUFFER_SIZE) ? (int)size : BUFFER_SIZE);
X
X      n = fread (buffer, sizeof (char), read_size, ifp);
X
X      if (n == 0)
X	read_error ();
X
X      for (p1 = p = buffer, e = buffer + n; p < e; p++)
X	{
X	  if (*p == '\n')
X	    {
X	      if ((m = p - p1) != 0)
X		{
X		  if (fwrite (p1, sizeof (char), m, ofp) < m)
X		    write_error ();
X		  crcsub (p1, m);
X		}
X	      putc (0x0d, ofp);
X	      if (feof (ofp))
X		write_error ();
X	      CRC_CHAR (0x0d);
X	      p1 = p;
X	      write_count ++;
X	    }
X	}
X      if ((m = p - p1) != 0)
X	{
X	  if (fwrite (p1, sizeof (char), m, ofp) < m)
X	    write_error ();
X	  crcsub (p1, m);
X	}
X
X      write_count += (long)n;
X      size -= (long)n;
X    }
X
X  crc_size = write_count;
X}
X
X/* read generic text file '0D0A' and write UNIX text file '0A' */
Xread_generic_text_file (ifp, ofp, size, crc_flag)
X     FILE	*ifp, *ofp;
X     long	size;
X     int	crc_flag;
X{
X  char		buffer[BUFFER_SIZE];
X  int		read_size, write_size, n, m;
X  register char *p, *p1, *e;
X
X  /* safty */
X  fflush (ofp);
X
X  while (size > 0)
X    {
X      read_size = ((size < BUFFER_SIZE) ? (int)size : BUFFER_SIZE);
X
X      n = fread (buffer, sizeof (char), read_size, ifp);
X
X      if (n == 0)
X	read_error ();
X
X      crcsub (buffer, n);
X
X      for (p1 = p = buffer, e = buffer + n; p < e; p ++)
X	{
X	  if (*p == 0x0d)
X	    {
X	      if ((m = p - p1) != 0)
X		{
X		  if (fwrite (p1, sizeof (char), m, ofp) < m)
X		    write_error ();
X		}
X	      p1 = p+1;
X	    }
X	}
X      if ((m = p - p1) != 0)
X	{
X	  if (fwrite (p1, sizeof (char), m, ofp) < m)
X	    write_error ();
X	}
X
X      size -= (long)n;
X    }
X}
X
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X
Xcopy_file (ifp, ofp, size)
X     FILE	*ifp, *ofp;
X     long	size;
X{
X  copy_binary_file (ifp, ofp, size, 0);
X}
X
X/*ARGSUSED*/
Xint decode_stored_crc (ifp, ofp, original_size, name)
X     FILE	*ifp, *ofp;
X     long	original_size;
X     char	*name;
X{
X  init_crc ();
X
X  if (text_mode)
X    {
X      read_generic_text_file (ifp, ofp, original_size, 1);
X      return crc_value;
X    }
X  else
X    {
X      copy_binary_file (ifp, ofp, original_size, 1);
X      return crc_value;
X    }
X}
X
X/*ARGSUSED*/
Xint decode_stored_nocrc (ifp, ofp, original_size, name)
X     FILE	*ifp, *ofp;
X     long	original_size;
X     char	*name;
X{
X  if (text_mode)
X    {
X      read_generic_text_file (ifp, ofp, original_size, 0);
X      return 0;			/* DUMMY */
X    }
X  else
X    {
X      copy_binary_file (ifp, ofp, original_size, 0);
X    }
X  return 0;			/* DUMMY */
X}
X
Xint encode_stored_crc (ifp, ofp, size, original_size_var, write_size_var)
X     FILE       *ifp, *ofp;
X     long       size;
X     long	*original_size_var;
X     long	*write_size_var;
X{
X  init_crc ();
X
X  if (text_mode)
X    {
X      write_generic_text_file (ifp, ofp, size);
X      *original_size_var = *write_size_var = crc_size;
X      return crc_value;
X    }
X  else
X    {
X      copy_binary_file (ifp, ofp, size, 1);
X      *original_size_var = size;
X      *write_size_var = size;
X      return crc_value;
X    }
X}
SHAR_EOF
chmod 0666 lhio.c || echo "restore of lhio.c fails"
echo "x - extracting lhio.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > lhio.h &&
X/*----------------------------------------------------------------------*/
X/*		File I/O module for LHarc UNIX				*/
X/*									*/
X/*		Copyright(C) MCMLXXXIX  Yooichi.Tagawa			*/
X/*									*/
X/*  V0.00  Original				1989.06.25  Y.Tagawa	*/
X/*  V0.03  Release #3  Beta Version		1989.07.02  Y.Tagawa	*/
X/*----------------------------------------------------------------------*/
X
Xextern int		text_mode;
X
Xextern unsigned int	crc_table[0x100];
Xextern unsigned int	crc_value;
Xextern int		crc_getc_cashe;
Xextern FILE		*crc_infile, *crc_outfile;
Xextern long		crc_size;
X
X
X#define CRC_CHAR(c)						\
X{ register unsigned int ctmp = crc_value ^ c; 			\
X    crc_value = (ctmp >> 8) ^ crc_table [ ctmp & 0xff ]; }
X
X
X
X#if defined (__GNUC__)
X/*#define inlnie*/
X
X/* DECODING */
X/* '0D0A' -> '0A' conversion and strip '1A' when text_mode */
Xstatic inline putc_crc (int c)
X{
X  CRC_CHAR (c);
X  if (!text_mode || (c != 0x0d && c != 0x1a))
X    {
X      putc (c, crc_outfile);
X    }
X}
X
X/* ENCODING */
X/* '0A' -> '0D0A' conversion when text_mode */
Xstatic inline int getc_crc ()
X{
X  int	c;
X
X  if (crc_getc_cashe != EOF)
X    {
X      c = crc_getc_cashe;
X      crc_getc_cashe = EOF;
X      CRC_CHAR (c);
X      crc_size++;
X    }
X  else if ((c = getc (crc_infile)) != EOF)
X    {
X      if (text_mode && c == 0x0a)
X	{
X	  crc_getc_cashe = c;
X	  c = 0x0d;
X	}
X      CRC_CHAR (c);
X      crc_size++;
X    }
X  return c;
X}
X#endif
SHAR_EOF
chmod 0666 lhio.h || echo "restore of lhio.h fails"
echo "x - extracting lzhuf.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > lzhuf.c &&
X/*----------------------------------------------------------------------*/
X/*		lzhuf.c : Encoding/Decoding module for LHarc		*/
X/*									*/
X/*	LZSS Algorithm			Haruhiko.Okumura		*/
X/*	Adaptic Huffman Encoding	1989.05.27  Haruyasu.Yoshizaki	*/
X/*									*/
X/*									*/
X/*	Modified for UNIX LHarc V0.01	1989.05.28  Y.Tagawa		*/
X/*	Modified for UNIX LHarc V0.02	1989.05.29  Y.Tagawa		*/
X/*	Modified for UNIX LHarc V0.03	1989.07.02  Y.Tagawa		*/
X/*----------------------------------------------------------------------*/
X
X/* Use ANSI sequences for using only one line per file but
X * indicator dots on next line */
X/* #define ANSI */
X
X#ifndef ANSI
X#define DOT       '.'
X#define BALL      'o'
X#else
X#define DOT       249
X#define BALL      3
X#define CURSORUP  "\033[A"
X#define ERASEEOL  "\033[K"
X#endif
X
X#include <stdio.h>
X
X#ifndef SELFMAIN
X#include "lhio.h"
X#else
X#define EXIT_SUCCESS	0
X#define EXIT_FAILURE	1
X#endif
X
X
X
XFILE *infile, *outfile;
Xlong textsize, codesize;
X
X
X#define INDICATOR_THRESHOLD	4096L
X#define MAX_INDICATOR_COUNT     78
Xlong indicator_count;
Xlong indicator_threshold;
X
X#ifdef SELFMAIN
Xint quiet = 0;
X#else
Xextern int quiet;
Xextern int output_to_test;
X#endif
X
X
X#ifdef SELFMAIN
X#define SETUP_PUTC_CRC(fp)	/* nothing */
X#define SETUP_GETC_CRC(fp)	/* nothing */
X#define PUTC_CRC(c)		putc((c),(outfile))
X#define GETC_CRC()		getc(infile)
X#define END_PUTC_CRC()
X#define END_GETC_CRC()
X#else
X#define SETUP_PUTC_CRC(fp)	crc_outfile = fp
X#define SETUP_GETC_CRC(fp)	crc_infile = fp
X#define PUTC_CRC(c)		putc_crc(c)
X#define GETC_CRC()		getc_crc()
X#define END_PUTC_CRC()
X#define END_GETC_CRC()
X#endif
X
X
X
X
X#ifdef SELFMAIN
Xvoid Error (message)
X	char *message;
X{
X	printf("\n%s\n", message);
X	exit(EXIT_FAILURE);
X}
X#endif
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*		LZSS ENCODING						*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X#define N		4096	/* buffer size */
X#define F		60	/* pre-sence buffer size */
X#define THRESHOLD	2
X#define NIL		N	/* term of tree */
X
Xunsigned char    text_buf[N + F - 1];
Xunsigned int     match_position, match_length;
Xint              lson[N + 1], rson[N + 1 + N], dad[N + 1];
Xunsigned char    same[N + 1];
X
X
X/* Initialize Tree */
XInitTree ()
X{
X	register int *p, *e;
X
X	for (p = rson + N + 1, e = rson + N + N; p <= e; )
X		*p++ = NIL;
X	for (p = dad, e = dad + N; p < e; )
X		*p++ = NIL;
X}
X
X
X/* Insert to node */
XInsertNode (r)
X	register int r;
X{
X	register int		p;
X	int			cmp;
X	register unsigned char	*key;
X	register unsigned int	c;
X	register unsigned int	i, j;
X
X	cmp = 1;
X	key = &text_buf[r];
X	i = key[1] ^ key[2];
X	i ^= i >> 4;
X	p = N + 1 + key[0] + ((i & 0x0f) << 8);
X	rson[r] = lson[r] = NIL;
X	match_length = 0;
X	i = j = 1;
X	for ( ; ; ) {
X		if (cmp >= 0) {
X			if (rson[p] != NIL) {
X				p = rson[p];
X				j = same[p];
X			} else {
X				rson[p] = r;
X				dad[r] = p;
X				same[r] = i;
X				return;
X			}
X		} else {
X			if (lson[p] != NIL) {
X				p = lson[p];
X				j = same[p];
X			} else {
X				lson[p] = r;
X				dad[r] = p;
X				same[r] = i;
X				return;
X			}
X		}
X
X		if (i > j) {
X			i = j;
X			cmp = key[i] - text_buf[p + i];
X		} else
X		if (i == j) {
X			for (; i < F; i++)
X				if ((cmp = key[i] - text_buf[p + i]) != 0)
X					break;
X		}
X
X		if (i > THRESHOLD) {
X			if (i > match_length) {
X				match_position = ((r - p) & (N - 1)) - 1;
X				if ((match_length = i) >= F)
X					break;
X			} else
X			if (i == match_length) {
X				if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
X					match_position = c;
X				}
X			}
X		}
X	}
X	same[r] = same[p];
X	dad[r] = dad[p];
X	lson[r] = lson[p];
X	rson[r] = rson[p];
X	dad[lson[p]] = r;
X	dad[rson[p]] = r;
X	if (rson[dad[p]] == p)
X		rson[dad[p]] = r;
X	else
X		lson[dad[p]] = r;
X	dad[p] = NIL;  /* remove p */
X}
X
X
Xlink (n, p, q)
X	int n, p, q;
X{
X	register unsigned char *s1, *s2, *s3;
X	if (p >= NIL) {
X		same[q] = 1;
X		return;
X	}
X	s1 = text_buf + p + n;
X	s2 = text_buf + q + n;
X	s3 = text_buf + p + F;
X	while (s1 < s3) {
X		if (*s1++ != *s2++) {
X			same[q] = s1 - 1 - text_buf - p;
X			return;
X		}
X	}
X	same[q] = F;
X}
X
X
Xlinknode (p, q, r)
X	int p, q, r;
X{
X	int cmp;
X
X	if ((cmp = same[q] - same[r]) == 0) {
X		link(same[q], p, r);
X	} else if (cmp < 0) {
X		same[r] = same[q];
X	}
X}
X
XDeleteNode (p)
X	register int p;
X{
X	register int  q;
X
X	if (dad[p] == NIL)
X		return;			/* has no linked */
X	if (rson[p] == NIL) {
X		if ((q = lson[p]) != NIL)
X			linknode(dad[p], p, q);
X	} else
X	if (lson[p] == NIL) {
X		q = rson[p];
X		linknode(dad[p], p, q);
X	} else {
X		q = lson[p];
X		if (rson[q] != NIL) {
X			do {
X				q = rson[q];
X			} while (rson[q] != NIL);
X			if (lson[q] != NIL)
X				linknode(dad[q], q, lson[q]);
X			link(1, q, lson[p]);
X			rson[dad[q]] = lson[q];
X			dad[lson[q]] = dad[q];
X			lson[q] = lson[p];
X			dad[lson[p]] = q;
X		}
X		link(1, dad[p], q);
X		link(1, q, rson[p]);
X		rson[q] = rson[p];
X		dad[rson[p]] = q;
X	}
X	dad[q] = dad[p];
X	if (rson[dad[p]] == p)
X		rson[dad[p]] = q;
X	else
X		lson[dad[p]] = q;
X	dad[p] = NIL;
X}
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*		HUFFMAN ENCODING					*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X#define N_CHAR  	(256 - THRESHOLD + F) /* {code : 0 .. N_CHAR-1} */
X#define T 		(N_CHAR * 2 - 1)	/* size of table */
X#define R 		(T - 1)			/* root position */
X#define MAX_FREQ	0x8000	/* tree update timing from frequency */
X
Xtypedef unsigned char uchar;
X
X
X
X/* TABLE OF ENCODE/DECODE for upper 6bits position information */
X
X/* for encode */
Xuchar p_len[64] = {
X	0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
X	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
X};
X
Xuchar p_code[64] = {
X	0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
X	0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
X	0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
X	0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
X	0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
X	0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
X	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
X	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
X};
X
X/* for decode */
Xuchar d_code[256] = {
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
X	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
X	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
X	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
X	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
X	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
X	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
X	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
X	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
X	0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
X	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
X	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
X	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
X	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
X	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
X	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
X	0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
X	0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
X	0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
X	0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
X	0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
X	0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
X	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
X	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
X};
X
Xuchar d_len[256] = {
X	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
X	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
X	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
X	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
X	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
X	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
X	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
X	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
X	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
X	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
X	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
X	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
X};
X
Xunsigned freq[T + 1];    /* frequency table */
X
Xint prnt[T + N_CHAR];    /* points to parent node */
X/* notes :
X   prnt[T .. T + N_CHAR - 1] used by
X   indicates leaf position that corresponding to code */
X
Xint son[T];              /* points to son node (son[i],son[i+]) */
X
Xunsigned getbuf = 0;
Xuchar getlen = 0;
X
X
X/* get one bit */
X/* returning in Bit 0 */
Xint GetBit ()
X{
X	register unsigned int dx = getbuf;
X	register unsigned int c;
X
X	if (getlen <= 8)
X		{
X			c = getc (infile);
X			if ((int)c < 0) c = 0;
X			dx |= c << (8 - getlen);
X			getlen += 8;
X		}
X	getbuf = dx << 1;
X	getlen--;
X	return (dx & 0x8000) ? 1 : 0;
X}
X
X/* get one byte */
X/* returning in Bit7...0 */
Xint GetByte ()
X{
X	register unsigned int dx = getbuf;
X	register unsigned c;
X
X	if (getlen <= 8) {
X		c = getc (infile);
X		if ((int)c < 0) c = 0;
X		dx |= c << (8 - getlen);
X		getlen += 8;
X	}
X	getbuf = dx << 8;
X	getlen -= 8;
X	return (dx >> 8) & 0xff;
X}
X
X/* get N bit */
X/* returning in Bit(N-1)...Bit 0 */
Xint GetNBits (n)
X	register unsigned int n;
X{
X	register unsigned int dx = getbuf;
X	register unsigned int c;
X	static int mask[17] = {
X		0x0000,
X		0x0001, 0x0003, 0x0007, 0x000f,
X		0x001f, 0x003f, 0x007f, 0x00ff,
X		0x01ff, 0x03ff, 0x07ff, 0x0fff,
X		0x1fff, 0x3fff, 0x0fff, 0xffff };
X	static int shift[17] = {
X		16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
X
X	if (getlen <= 8)
X		{
X			c = getc (infile);
X			if ((int)c < 0) c = 0;
X			dx |= c << (8 - getlen);
X			getlen += 8;
X		}
X	getbuf = dx << n;
X	getlen -= n;
X	return (dx >> shift[n]) & mask[n];
X}
X
Xunsigned putbuf = 0;
Xuchar putlen = 0;
X
X/* output C bits */
XPutcode (l, c)
X	register int l;
X	register unsigned int c;
X{
X	register len = putlen;
X	register unsigned int b = putbuf;
X	b |= c >> len;
X	if ((len += l) >= 8) {
X		putc (b >> 8, outfile);
X		if ((len -= 8) >= 8) {
X			putc (b, outfile);
X			codesize += 2;
X			len -= 8;
X			b = c << (l - len);
X		} else {
X			b <<= 8;
X			codesize++;
X		}
X	}
X	putbuf = b;
X	putlen = len;
X}
X
X
X/* Initialize tree */
X
XStartHuff ()
X{
X	register int i, j;
X
X	for (i = 0; i < N_CHAR; i++) {
X		freq[i] = 1;
X		son[i] = i + T;
X		prnt[i + T] = i;
X	}
X	i = 0; j = N_CHAR;
X	while (j <= R) {
X		freq[j] = freq[i] + freq[i + 1];
X		son[j] = i;
X		prnt[i] = prnt[i + 1] = j;
X		i += 2; j++;
X	}
X	freq[T] = 0xffff;
X	prnt[R] = 0;
X	putlen = getlen = 0;
X	putbuf = getbuf = 0;
X}
X
X
X/* reconstruct tree */
Xreconst ()
X{
X	register int i, j, k;
X	register unsigned f;
X
X	/* correct leaf node into of first half,
X	   and set these freqency to (freq+1)/2       */
X	j = 0;
X	for (i = 0; i < T; i++) {
X		if (son[i] >= T) {
X			freq[j] = (freq[i] + 1) / 2;
X			son[j] = son[i];
X			j++;
X		}
X	}
X	/* build tree.  Link sons first */
X	for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
X		k = i + 1;
X		f = freq[j] = freq[i] + freq[k];
X		for (k = j - 1; f < freq[k]; k--);
X		k++;
X		{	register unsigned *p, *e;
X			for (p = &freq[j], e = &freq[k]; p > e; p--)
X				p[0] = p[-1];
X			freq[k] = f;
X		}
X		{	register int *p, *e;
X			for (p = &son[j], e = &son[k]; p > e; p--)
X				p[0] = p[-1];
X			son[k] = i;
X		}
X	}
X	/* link parents */
X	for (i = 0; i < T; i++) {
X		if ((k = son[i]) >= T) {
X			prnt[k] = i;
X		} else {
X			prnt[k] = prnt[k + 1] = i;
X		}
X	}
X}
X
X
X/* update given code's frequency, and update tree */
X
Xupdate (c)
X	unsigned int	c;
X{
X	register unsigned *p;
X	register int i, j, k, l;
X
X	if (freq[R] == MAX_FREQ) {
X		reconst();
X	}
X	c = prnt[c + T];
X	do {
X		k = ++freq[c];
X
X		/* swap nodes when become wrong frequency order. */
X		if (k > freq[l = c + 1]) {
X			for (p = freq+l+1; k > *p++; ) ;
X			l = p - freq - 2;
X			freq[c] = p[-2];
X			p[-2] = k;
X
X			i = son[c];
X			prnt[i] = l;
X			if (i < T) prnt[i + 1] = l;
X
X			j = son[l];
X			son[l] = i;
X
X			prnt[j] = c;
X			if (j < T) prnt[j + 1] = c;
X			son[c] = j;
X
X			c = l;
X		}
X	} while ((c = prnt[c]) != 0);	/* loop until reach to root */
X}
X
X/* unsigned code, len; */
X
XEncodeChar (c)
X	unsigned c;
X{
X	register int *p;
X	register unsigned long i;
X	register int j, k;
X
X	i = 0;
X	j = 0;
X	p = prnt;
X	k = p[c + T];
X
X	/* trace links from leaf node to root */
X	do {
X		i >>= 1;
X
X		/* if node index is odd, trace larger of sons */
X		if (k & 1) i += 0x80000000;
X
X		j++;
X	} while ((k = p[k]) != R) ;
X	if (j > 16) {
X		Putcode(16, (unsigned int)(i >> 16));
X		Putcode(j - 16, (unsigned int)i);
X	} else {
X		Putcode(j, (unsigned int)(i >> 16));
X	}
X/*	code = i; */
X/* 	len = j; */
X	update(c);
X}
X
XEncodePosition (c)
X	unsigned c;
X{
X	unsigned i;
X
X	/* output upper 6bit from table */
X	i = c >> 6;
X	Putcode((int)(p_len[i]), (unsigned int)(p_code[i]) << 8);
X
X	/* output lower 6 bit */
X	Putcode(6, (unsigned int)(c & 0x3f) << 10);
X}
X
XEncodeEnd ()
X{
X	if (putlen) {
X		putc(putbuf >> 8, outfile);
X		codesize++;
X	}
X}
X
Xint DecodeChar ()
X{
X	register unsigned c;
X
X	c = son[R];
X
X	/* trace from root to leaf,
X	   got bit is 0 to small(son[]), 1 to large (son[]+1) son node */
X	while (c < T) {
X		c += GetBit();
X		c = son[c];
X	}
X	c -= T;
X	update(c);
X	return c;
X}
X
Xint DecodePosition ()
X{
X	unsigned i, j, c;
X
X	/* decode upper 6bit from table */
X	i = GetByte();
X	c = (unsigned)d_code[i] << 6;
X	j = d_len[i];
X
X	/* get lower 6bit */
X	j -= 2;
X	return c | (((i << j) | GetNBits (j)) & 0x3f);
X}
X
X
XEncode ()
X{
X	register int  i, c, len, r, s, last_match_length;
X
X	if (textsize == 0)
X		return;
X
X	textsize = 0;
X	StartHuff();
X	InitTree();
X	s = 0;
X	r = N - F;
X	for (i = s; i < r; i++)
X		text_buf[i] = ' ';
X	for (len = 0; len < F && (c = GETC_CRC()) != EOF; len++)
X		text_buf[r + len] = c;
X	textsize = len;
X	for (i = 1; i <= F; i++)
X		InsertNode(r - i);
X	InsertNode(r);
X	do {
X		if (match_length > len)
X			match_length = len;
X		if (match_length <= THRESHOLD) {
X			match_length = 1;
X			EncodeChar(text_buf[r]);
X		} else {
X			EncodeChar(255 - THRESHOLD + match_length);
X			EncodePosition(match_position);
X		}
X		last_match_length = match_length;
X		for (i = 0; i < last_match_length &&
X				(c = GETC_CRC()) != EOF; i++) {
X			DeleteNode(s);
X			text_buf[s] = c;
X			if (s < F - 1)
X				text_buf[s + N] = c;
X			s = (s + 1) & (N - 1);
X			r = (r + 1) & (N - 1);
X			InsertNode(r);
X		}
X
X		textsize += i;
X		if ((textsize > indicator_count) && !quiet) {
X			putchar (BALL);
X			fflush (stdout);
X			indicator_count += indicator_threshold;
X		}
X		while (i++ < last_match_length) {
X			DeleteNode(s);
X			s = (s + 1) & (N - 1);
X			r = (r + 1) & (N - 1);
X			if (--len) InsertNode(r);
X		}
X	} while (len > 0);
X	EncodeEnd();
X	END_GETC_CRC ();
X}
X
XDecode ()
X{
X	register int	i, j, k, r, c;
X	register long	count;
X
X#ifdef SELFMAIN
X	if (textsize == 0)
X		return;
X#endif
X	StartHuff();
X	for (i = 0; i < N - F; i++)
X		text_buf[i] = ' ';
X	r = N - F;
X	for (count = 0; count < textsize; ) {
X		c = DecodeChar();
X		if (c < 256) {
X			PUTC_CRC (c);
X			text_buf[r++] = c;
X			r &= (N - 1);
X			count++;
X		} else {
X			i = (r - DecodePosition() - 1) & (N - 1);
X			j = c - 255 + THRESHOLD;
X			for (k = 0; k < j; k++) {
X				c = text_buf[(i + k) & (N - 1)];
X				PUTC_CRC (c);
X				text_buf[r++] = c;
X				r &= (N - 1);
X				count++;
X			}
X		}
X
X		if (!quiet && (count > indicator_count)) {
X			putchar (BALL);
X			fflush (stdout);
X			indicator_count += indicator_threshold;
X		}
X	}
X	END_PUTC_CRC ();
X}
X
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*		LARC							*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X#define F_OLD	18	/* look ahead buffer size for LArc */
X
X/* intialize buffer for LArc type 5 */
XInitBuf ()
X{
X	register unsigned char *p = text_buf;
X	register int i, j;
X	for (i = 0; i < 256; i ++)
X		for (j = 0; j < 13; j ++)
X			*p ++ = i;
X	for (i = 0; i < 256; i ++)
X		*p ++ = i;
X	for (i = 0; i < 256; i ++)
X		*p ++ = 255 - i;
X	for (i = 0; i < 128; i ++)
X		*p ++ = 0;
X	for (i = 0; i < 128; i ++)
X		*p ++ = 0x20;
X}
X
X/* Decode LArc type 5 */
XDecodeOld ()
X{
X	register int si, di;
X	register long count;
X	int	dl, dh, al, cx;
X	if (textsize == 0)
X		return;
X
X	InitBuf ();
X	di = N - F_OLD;
X	dl = 0x80;
X
X	for (count = 0; count < textsize; ) {
X		dl = ((dl << 1) | (dl >> 7)) & 0xff;
X		if (dl & 0x01)
X			dh = getc (infile);
X		al = getc (infile);
X		if ((dh & dl) != 0) {
X			PUTC_CRC (al);
X			text_buf[di] = al;
X			di = (di + 1) & (N - 1);
X			count ++;
X		} else {
X			cx = getc (infile);
X			si = (al & 0x00ff) | ((cx << 4) & 0x0f00);
X			cx = (cx & 0x000f) + 3;
X			count += cx;
X			do {
X				text_buf[di] = al = text_buf[si];
X				PUTC_CRC (al);
X				si = (si + 1) & (N - 1);
X				di = (di + 1) & (N - 1);
X			} while (--cx != 0) ;
X		}
X
X		if (!quiet && (count > indicator_count)) {
X			putchar (BALL);
X			fflush (stdout);
X			indicator_count += indicator_threshold;
X		}
X	}
X	END_PUTC_CRC ();
X}
X
X
X
X/*----------------------------------------------------------------------*/
X/*									*/
X/*		Global Entries for Archiver Driver			*/
X/*									*/
X/*----------------------------------------------------------------------*/
X
X
Xstart_indicator (name, size, msg)
X	char *name;
X	long size;
X	char *msg;
X{
X	long	i;
X	int	m;
X
X	if (quiet)
X		return;
X
X#ifdef ANSI
X	m = MAX_INDICATOR_COUNT;
X#else
X	m = MAX_INDICATOR_COUNT - strlen (name);
X#endif
X	if (m < 0)
X		m = 3;		/* (^_^) */
X
X#ifdef ANSI
X        printf ("\r%s - %s:\n", name, msg);
X#else
X        printf ("\r%s - %s :  ", name, msg);
X#endif
X
X	indicator_threshold =
X		((size  + (m * INDICATOR_THRESHOLD - 1)) /
X		 (m * INDICATOR_THRESHOLD) *
X		 INDICATOR_THRESHOLD);
X
X	/* bug fix for files with size==0 28.03.1990 SB */
X	if (indicator_threshold == 0)
X		indicator_threshold = INDICATOR_THRESHOLD;
X	/************************************************/
X
X	i = ((size + (indicator_threshold - 1)) / indicator_threshold);
X	while (i--)
X		putchar (DOT);
X	indicator_count = 0;
X#ifdef ANSI
X        printf ("\r%s%s - %s:\n", CURSORUP, name, msg);
X#else
X        printf ("\r%s - %s :  ", name, msg);
X#endif
X	fflush (stdout);
X}
X
Xfinish_indicator2 (name, msg, pcnt)
X	char *name;
X	char *msg;
X	int pcnt;
X{
X	if (quiet)
X		return;
X
X	if (pcnt > 100) pcnt = 100;	/* (^_^) */
X#ifdef ANSI
X        printf ("\r%s%s - %s(%d%%)\n%s", CURSORUP, name, msg, pcnt, ERASEEOL);
X#else
X        printf ("\r%s - %s(%d%%)\n", name, msg, pcnt);
X#endif
X	fflush (stdout);
X}
X
Xfinish_indicator (name, msg)
X	char *name;
X	char *msg;
X{
X	if (quiet)
X		return;
X
X#ifdef ANSI
X        printf ("\r%s%s - %s\n%s", CURSORUP, name, msg, ERASEEOL);
X#else
X        printf ("\r%s - %s\n", name, msg);
X#endif
X	fflush (stdout);
X}
X
X
X#ifndef SELFMAIN
Xint encode_lzhuf (infp, outfp, size, original_size_var, packed_size_var, name)
X	FILE *infp;
X	FILE *outfp;
X	long size;
X	long *original_size_var;
X	long *packed_size_var;
X	char *name;
X{
X	infile = infp;
X	outfile = outfp;
X	SETUP_GETC_CRC(infp);
X	textsize = size;
X	codesize = 0;
X	init_crc ();
X	start_indicator (name, size, "Freezing");
X	Encode ();
X	finish_indicator2 (name, "Frozen",
X			   (int)((codesize * 100L) / crc_size));
X	*packed_size_var = codesize;
X	*original_size_var = crc_size;
X	return crc_value;
X}
X
Xint decode_lzhuf (infp, outfp, original_size, name)
X	FILE *infp;
X	FILE *outfp;
X	long original_size;
X	char *name;
X{
X	infile = infp;
X	outfile = outfp;
X	SETUP_PUTC_CRC(outfp);
X	textsize = original_size;
X	init_crc ();
X        start_indicator (name, original_size,
X                         (output_to_test ? "Testing" : "Melting"));
X	Decode ();
X        finish_indicator (name, (output_to_test ? "Tested  " : "Melted  "));
X	return crc_value;
X}
X
X
Xint decode_larc (infp, outfp, original_size, name)
X	FILE *infp, *outfp;
X	long original_size;
X	char *name;
X{
X	infile = infp;
X	outfile = outfp;
X	SETUP_PUTC_CRC(outfp);
X	textsize = original_size;
X	init_crc ();
X        start_indicator (name, original_size,
X                         (output_to_test ? "Testing" : "Melting"));
X	DecodeOld ();
X        finish_indicator (name, (output_to_test ? "Tested  " : "Melted  "));
X	return crc_value;
X}
X#endif
X
X#ifdef SELFMAIN
Xint main (argc, argv)
X	int argc;
X	char *argv[];
X{
X	char  *s;
X	int i;
X
X	indicator_count = 0;
X	indicator_threshold = 1024;
X	textsize = codesize = 0;
X	if (argc != 4) {
X		printf ("\
Xusage: lzhuf e in_file out_file (packing)\n\
X       lzhuf d in_file out_file (unpacking)\n");
X		return EXIT_FAILURE;
X	}
X	if ((s = argv[1], ((*s != 'e') && (*s != 'd')) || s[1] != '\0') ||
X	    (s = argv[2], (infile  = fopen(s, "rb")) == NULL) ||
X	    (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
X		printf("??? %s\n", s);
X		return EXIT_FAILURE;
X	}
X	if (argv[1][0] == 'e') {
X		/* Get original text size and output it */
X		fseek(infile, 0L, 2);
X		textsize = ftell(infile);
X		rewind (infile);
X		if (fwrite(&textsize, sizeof textsize, 1, outfile) < 1)
X			Error("cannot write");
X
X		start_indicator (argv[2], textsize, "Freezing");
X		Encode();
X		finith_indicator2 (argv[2], "Frozen",
X				   (int)((codesize * 100L) / textsize));
X
X		printf("input : %ld bytes\n", textsize);
X		printf("output: %ld bytes\n", codesize);
X	} else {
X		/* Read original text size */
X		if (fread(&textsize, sizeof textsize, 1, infile) < 1)
X			Error("cannot read");
X
X		start_indicator (argv[2], textsize, "Melting");
X		Decode();
X		finish_indicator (argv[2], "Melted  ");
X	}
X	fclose(infile);
X	fclose(outfile);
X	return EXIT_SUCCESS;
X}
X#endif
X
X
X/* These lines are used in GNU-Emacs */
X/* Local Variables: */
X/* comment-column:40 */
X/* tab-width:8 */
X/* c-indent-level:8 */
X/* c-continued-statement-offset:8 */
X/* c-argdecl-indent:8 */
X/* End: */
SHAR_EOF
chmod 0666 lzhuf.c || echo "restore of lzhuf.c fails"
echo "x - extracting mktemp.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > mktemp.c &&
X/* MKTEMP.C using TMP environment variable */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <io.h>
X
Xvoid Mktemp(char *file)
X{
X  char fname[32], *tmp;
X
X  tmp = getenv("TMP");
X
X  if ( tmp != NULL )
X  {
X    strcpy(fname, file);
X    strcpy(file, tmp);
X
X    if ( file[strlen(file) - 1] != '\\' )
X      strcat(file, "\\");
X
X    strcat(file, fname);
X  }
X
X  mktemp(file);
X}
X
X/* End of MKTEMP.C */
SHAR_EOF
chmod 0666 mktemp.c || echo "restore of mktemp.c fails"
echo "x - extracting pipes.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > pipes.c &&
X/* a simulation for the Unix popen() and pclose() calls on MS-DOS */
X/* only one pipe can be open at a time */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X
Xstatic char pipename[128], command[128];
Xstatic int wrpipe;
X
Xextern void Mktemp(char *);
X
XFILE *popen(char *cmd, char *flags)
X{
X  wrpipe = (strchr(flags, 'w') != NULL);
X
X  if ( wrpipe )
X  {
X    strcpy(command, cmd);
X    strcpy(pipename, "~WXXXXXX");
X    Mktemp(pipename);
X    return fopen(pipename, flags);  /* ordinary file */
X  }
X  else
X  {
X    strcpy(pipename, "~RXXXXXX");
X    Mktemp(pipename);
X    strcpy(command, cmd);
X    strcat(command, ">");
X    strcat(command, pipename);
X    system(command);
X    return fopen(pipename, flags);  /* ordinary file */
X  }
X}
X
Xint pclose(FILE *pipe)
X{
X  int rc;
X
X  if ( fclose(pipe) == EOF )
X    return EOF;
X
X  if ( wrpipe )
X  {
X    if ( command[strlen(command) - 1] == '!' )
X      command[strlen(command) - 1] = 0;
X    else
X      strcat(command, "<");
X
X    strcat(command, pipename);
X    rc = system(command);
X    unlink(pipename);
X    return rc;
X  }
X  else
X  {
X    unlink(pipename);
X    return 0;
X  }
X}
SHAR_EOF
chmod 0666 pipes.c || echo "restore of pipes.c fails"
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0

-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
    VMS is a text-only adventure game. If you win you can use unix.