home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / lhaxenix.zoo / lharc.xenix
Encoding:
Text File  |  1990-04-03  |  102.4 KB  |  4,506 lines

  1.  
  2. #! /bin/sh
  3. # This is a shell archive.  Remove anything before this line, then unpack
  4. # it by saving it into a file and typing "sh file".  To overwrite existing
  5. # files, type "sh file -c".  You can also feed this as standard input via
  6. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  7. # will see the following message at the end:
  8. #        "End of shell archive."
  9. # Contents:  clharc.cs clharc.def dir_dos.c dir_os2.c lharc.c lhdir.h
  10. #   lhio.c lhio.h lzhuf.c makefile mktemp.c pipes.c readme rename.c
  11. # Wrapped by glenn@stsim on Tue Mar 27 19:12:19 1990
  12. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  13. if test -f clharc.cs -a "${1}" != "-c" ; then 
  14.   echo shar: Will not over-write existing file \"clharc.cs\"
  15. else
  16. echo shar: Extracting \"clharc.cs\" \(117 characters\)
  17. sed "s/^X//" >clharc.cs <<'END_OF_clharc.cs'
  18. X(-W1 lharc.c lhio.c dir_os2.c mktemp.c pipes.c)
  19. X(-W1 -Ox lzhuf.c)
  20. Xsetargv.obj
  21. Xclharc.def
  22. Xclharc.exe
  23. X-as -lb -s0x2000
  24. END_OF_clharc.cs
  25. if test 117 -ne `wc -c <clharc.cs`; then
  26.     echo shar: \"clharc.cs\" unpacked with wrong size!
  27. fi
  28. # end of overwriting check
  29. fi
  30. if test -f clharc.def -a "${1}" != "-c" ; then 
  31.   echo shar: Will not over-write existing file \"clharc.def\"
  32. else
  33. echo shar: Extracting \"clharc.def\" \(74 characters\)
  34. sed "s/^X//" >clharc.def <<'END_OF_clharc.def'
  35. XNAME CLHARC WINDOWCOMPAT
  36. XDESCRIPTION 'C-LHarc 1.00 - for MS-DOS and OS/2'
  37. END_OF_clharc.def
  38. if test 74 -ne `wc -c <clharc.def`; then
  39.     echo shar: \"clharc.def\" unpacked with wrong size!
  40. fi
  41. # end of overwriting check
  42. fi
  43. if test -f dir_dos.c -a "${1}" != "-c" ; then 
  44.   echo shar: Will not over-write existing file \"dir_dos.c\"
  45. else
  46. echo shar: Extracting \"dir_dos.c\" \(3587 characters\)
  47. sed "s/^X//" >dir_dos.c <<'END_OF_dir_dos.c'
  48. X/*
  49. X * @(#)dir.c 1.4 87/11/06    Public Domain.
  50. X *
  51. X *  A public domain implementation of BSD directory routines for
  52. X *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  53. X *  August 1897
  54. X *  Modified to use modern MS C library functions by Kai Uwe Rommel
  55. X *  December 1989
  56. X */
  57. X
  58. X#include    <sys/types.h>
  59. X#include    <sys/stat.h>
  60. X#include    <sys/dir.h>
  61. X#include    <malloc.h>
  62. X#include    <string.h>
  63. X
  64. X#include        <dos.h>
  65. X
  66. X#ifndef    NULL
  67. X# define    NULL    0
  68. X#endif    /* NULL */
  69. X
  70. X#ifndef    MAXPATHLEN
  71. X# define    MAXPATHLEN    255
  72. X#endif    /* MAXPATHLEN */
  73. X
  74. X/* attribute stuff */
  75. X#define    A_RONLY        0x01
  76. X#define    A_HIDDEN    0x02
  77. X#define    A_SYSTEM    0x04
  78. X#define    A_LABEL        0x08
  79. X#define    A_DIR        0x10
  80. X#define    A_ARCHIVE    0x20
  81. X
  82. X
  83. X#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
  84. X
  85. X#define ATTRIBUTES      (A_DIR)
  86. X/* #define ATTRIBUTES      (A_DIR | A_HIDDEN | A_SYSTEM) */
  87. X/* #define ATTRIBUTES      (A_RONLY | A_SYSTEM | A_DIR) */
  88. X
  89. Xstatic  char    *getdirent(char *);
  90. Xstatic    void    free_dircontents(struct _dircontents *);
  91. X
  92. Xstatic struct find_t find;
  93. X
  94. X
  95. XDIR    *
  96. Xopendir(name)
  97. X    char    *name;
  98. X{
  99. X    struct    stat        statb;
  100. X    DIR            *dirp;
  101. X    char            c;
  102. X    char            *s;
  103. X    struct _dircontents    *dp;
  104. X    char            nbuf[MAXPATHLEN + 1];
  105. X
  106. X    if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
  107. X        return (DIR *) NULL;
  108. X    if (Newisnull(dirp, DIR))
  109. X        return (DIR *) NULL;
  110. X    if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
  111. X        (void) strcat(strcpy(nbuf, name), "\\*.*");
  112. X    else
  113. X        (void) strcat(strcpy(nbuf, name), "*.*");
  114. X    dirp->dd_loc = 0;
  115. X        dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
  116. X
  117. X    if ((s = getdirent(nbuf)) == (char *) NULL)
  118. X        return dirp;
  119. X    do {
  120. X        if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
  121. X            malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
  122. X        {
  123. X            if (dp)
  124. X                free((char *) dp);
  125. X            free_dircontents(dirp->dd_contents);
  126. X            return (DIR *) NULL;
  127. X        }
  128. X        if (dirp->dd_contents)
  129. X            dirp->dd_cp = dirp->dd_cp->_d_next = dp;
  130. X        else
  131. X            dirp->dd_contents = dirp->dd_cp = dp;
  132. X        (void) strcpy(dp->_d_entry, s);
  133. X        dp->_d_next = (struct _dircontents *) NULL;
  134. X        } while ((s = getdirent((char *) NULL)) != (char *) NULL);
  135. X
  136. X    dirp->dd_cp = dirp->dd_contents;
  137. X
  138. X    return dirp;
  139. X}
  140. X
  141. Xvoid
  142. Xclosedir(dirp)
  143. X    DIR    *dirp;
  144. X{
  145. X    free_dircontents(dirp->dd_contents);
  146. X    free((char *) dirp);
  147. X}
  148. X
  149. Xstruct direct    *
  150. Xreaddir(dirp)
  151. X    DIR    *dirp;
  152. X{
  153. X    static    struct direct    dp;
  154. X
  155. X    if (dirp->dd_cp == (struct _dircontents *) NULL)
  156. X        return (struct direct *) NULL;
  157. X    dp.d_namlen = dp.d_reclen =
  158. X        strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
  159. X    strlwr(dp.d_name);        /* JF */
  160. X    dp.d_ino = 0;
  161. X    dirp->dd_cp = dirp->dd_cp->_d_next;
  162. X    dirp->dd_loc++;
  163. X
  164. X    return &dp;
  165. X}
  166. X
  167. Xvoid
  168. Xseekdir(dirp, off)
  169. X    DIR    *dirp;
  170. X    long    off;
  171. X{
  172. X    long            i = off;
  173. X    struct _dircontents    *dp;
  174. X
  175. X    if (off < 0)
  176. X        return;
  177. X    for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
  178. X        ;
  179. X    dirp->dd_loc = off - (i + 1);
  180. X    dirp->dd_cp = dp;
  181. X}
  182. X
  183. Xlong
  184. Xtelldir(dirp)
  185. X    DIR    *dirp;
  186. X{
  187. X    return dirp->dd_loc;
  188. X}
  189. X
  190. Xstatic    void
  191. Xfree_dircontents(dp)
  192. X    struct    _dircontents    *dp;
  193. X{
  194. X    struct _dircontents    *odp;
  195. X
  196. X    while (dp) {
  197. X        if (dp->_d_entry)
  198. X            free(dp->_d_entry);
  199. X        dp = (odp = dp)->_d_next;
  200. X        free((char *) odp);
  201. X    }
  202. X}
  203. X
  204. Xstatic char *getdirent(dir)
  205. Xchar *dir;
  206. X{
  207. X  int done;
  208. X
  209. X  if (dir != (char *) NULL)
  210. X    done = _dos_findfirst(dir, ATTRIBUTES, &find);
  211. X  else                                  /* get next entry */
  212. X    done = _dos_findnext(&find);
  213. X
  214. X  if (done==0)
  215. X    return find.name;
  216. X  else
  217. X    return (char *) NULL;
  218. X}
  219. X
  220. X
  221. Xsetfilemode(char *name, unsigned attr)
  222. X{
  223. X  _dos_setfileattr(name, attr);
  224. X}
  225. X
  226. Xgetfilemode(char *name, unsigned *attr)
  227. X{
  228. X  _dos_getfileattr(name, attr);
  229. X}
  230. END_OF_dir_dos.c
  231. if test 3587 -ne `wc -c <dir_dos.c`; then
  232.     echo shar: \"dir_dos.c\" unpacked with wrong size!
  233. fi
  234. # end of overwriting check
  235. fi
  236. if test -f dir_os2.c -a "${1}" != "-c" ; then 
  237.   echo shar: Will not over-write existing file \"dir_os2.c\"
  238. else
  239. echo shar: Extracting \"dir_os2.c\" \(3837 characters\)
  240. sed "s/^X//" >dir_os2.c <<'END_OF_dir_os2.c'
  241. X/*
  242. X * @(#)dir.c 1.4 87/11/06    Public Domain.
  243. X *
  244. X *  A public domain implementation of BSD directory routines for
  245. X *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  246. X *  August 1897
  247. X *  Ported to OS/2 by Kai Uwe Rommel
  248. X *  December 1989
  249. X */
  250. X
  251. X#include    <sys/types.h>
  252. X#include    <sys/stat.h>
  253. X#include    <sys/dir.h>
  254. X#include    <malloc.h>
  255. X#include    <string.h>
  256. X
  257. X#define INCL_NOPM
  258. X#include <os2.h>
  259. X
  260. X#ifndef    NULL
  261. X# define    NULL    0
  262. X#endif    /* NULL */
  263. X
  264. X#ifndef    MAXPATHLEN
  265. X# define    MAXPATHLEN    255
  266. X#endif    /* MAXPATHLEN */
  267. X
  268. X/* attribute stuff */
  269. X#define    A_RONLY        0x01
  270. X#define    A_HIDDEN    0x02
  271. X#define    A_SYSTEM    0x04
  272. X#define    A_LABEL        0x08
  273. X#define    A_DIR        0x10
  274. X#define    A_ARCHIVE    0x20
  275. X
  276. X
  277. X#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
  278. X
  279. X#define ATTRIBUTES      (A_DIR)
  280. X/* #define ATTRIBUTES      (A_DIR | A_HIDDEN | A_SYSTEM) */
  281. X/* #define ATTRIBUTES      (A_RONLY | A_SYSTEM | A_DIR) */
  282. X
  283. Xstatic  char    *getdirent(char *);
  284. Xstatic    void    free_dircontents(struct _dircontents *);
  285. X
  286. Xstatic HDIR hdir;
  287. Xstatic USHORT count;
  288. Xstatic FILEFINDBUF find;
  289. X
  290. X
  291. XDIR    *
  292. Xopendir(name)
  293. X    char    *name;
  294. X{
  295. X    struct    stat        statb;
  296. X    DIR            *dirp;
  297. X    char            c;
  298. X    char            *s;
  299. X    struct _dircontents    *dp;
  300. X    char            nbuf[MAXPATHLEN + 1];
  301. X
  302. X    if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
  303. X        return (DIR *) NULL;
  304. X    if (Newisnull(dirp, DIR))
  305. X        return (DIR *) NULL;
  306. X    if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
  307. X        (void) strcat(strcpy(nbuf, name), "\\*.*");
  308. X    else
  309. X        (void) strcat(strcpy(nbuf, name), "*.*");
  310. X    dirp->dd_loc = 0;
  311. X        dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
  312. X
  313. X    if ((s = getdirent(nbuf)) == (char *) NULL)
  314. X        return dirp;
  315. X    do {
  316. X        if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
  317. X            malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
  318. X        {
  319. X            if (dp)
  320. X                free((char *) dp);
  321. X            free_dircontents(dirp->dd_contents);
  322. X            return (DIR *) NULL;
  323. X        }
  324. X        if (dirp->dd_contents)
  325. X            dirp->dd_cp = dirp->dd_cp->_d_next = dp;
  326. X        else
  327. X            dirp->dd_contents = dirp->dd_cp = dp;
  328. X        (void) strcpy(dp->_d_entry, s);
  329. X        dp->_d_next = (struct _dircontents *) NULL;
  330. X        } while ((s = getdirent((char *) NULL)) != (char *) NULL);
  331. X
  332. X    dirp->dd_cp = dirp->dd_contents;
  333. X
  334. X    return dirp;
  335. X}
  336. X
  337. Xvoid
  338. Xclosedir(dirp)
  339. X    DIR    *dirp;
  340. X{
  341. X    free_dircontents(dirp->dd_contents);
  342. X    free((char *) dirp);
  343. X}
  344. X
  345. Xstruct direct    *
  346. Xreaddir(dirp)
  347. X    DIR    *dirp;
  348. X{
  349. X    static    struct direct    dp;
  350. X
  351. X    if (dirp->dd_cp == (struct _dircontents *) NULL)
  352. X        return (struct direct *) NULL;
  353. X    dp.d_namlen = dp.d_reclen =
  354. X        strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
  355. X    strlwr(dp.d_name);        /* JF */
  356. X    dp.d_ino = 0;
  357. X    dirp->dd_cp = dirp->dd_cp->_d_next;
  358. X    dirp->dd_loc++;
  359. X
  360. X    return &dp;
  361. X}
  362. X
  363. Xvoid
  364. Xseekdir(dirp, off)
  365. X    DIR    *dirp;
  366. X    long    off;
  367. X{
  368. X    long            i = off;
  369. X    struct _dircontents    *dp;
  370. X
  371. X    if (off < 0)
  372. X        return;
  373. X    for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
  374. X        ;
  375. X    dirp->dd_loc = off - (i + 1);
  376. X    dirp->dd_cp = dp;
  377. X}
  378. X
  379. Xlong
  380. Xtelldir(dirp)
  381. X    DIR    *dirp;
  382. X{
  383. X    return dirp->dd_loc;
  384. X}
  385. X
  386. Xstatic    void
  387. Xfree_dircontents(dp)
  388. X    struct    _dircontents    *dp;
  389. X{
  390. X    struct _dircontents    *odp;
  391. X
  392. X    while (dp) {
  393. X        if (dp->_d_entry)
  394. X            free(dp->_d_entry);
  395. X        dp = (odp = dp)->_d_next;
  396. X        free((char *) odp);
  397. X    }
  398. X}
  399. X
  400. Xstatic char *getdirent(dir)
  401. Xchar *dir;
  402. X{
  403. X  int done;
  404. X
  405. X  if (dir != (char *) NULL)
  406. X  {                                     /* get first entry */
  407. X    hdir = HDIR_CREATE;
  408. X    count = 1;
  409. X    done = DosFindFirst(dir, &hdir, ATTRIBUTES,
  410. X                        &find, sizeof(find), &count, 0L);
  411. X  }
  412. X  else                                  /* get next entry */
  413. X    done = DosFindNext(hdir, &find, sizeof(find), &count);
  414. X
  415. X  if (done==0)
  416. X    return find.achName;
  417. X  else
  418. X  {
  419. X    DosFindClose(hdir);
  420. X    return (char *) NULL;
  421. X  }
  422. X}
  423. X
  424. X
  425. Xsetfilemode(char *name, unsigned attr)
  426. X{
  427. X  DosSetFileMode(name, attr, 0L);
  428. X}
  429. X
  430. Xgetfilemode(char *name, unsigned *attr)
  431. X{
  432. X  DosQFileMode(name, (PUSHORT) attr, 0L);
  433. X}
  434. END_OF_dir_os2.c
  435. if test 3837 -ne `wc -c <dir_os2.c`; then
  436.     echo shar: \"dir_os2.c\" unpacked with wrong size!
  437. fi
  438. # end of overwriting check
  439. fi
  440. if test -f lharc.c -a "${1}" != "-c" ; then 
  441.   echo shar: Will not over-write existing file \"lharc.c\"
  442. else
  443. echo shar: Extracting \"lharc.c\" \(49791 characters\)
  444. sed "s/^X//" >lharc.c <<'END_OF_lharc.c'
  445. X/*----------------------------------------------------------------------*/
  446. X/*        LHarc Archiver Driver for UNIX                */
  447. X/*                                    */
  448. X/*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  449. X/*        Thanks to H.Yoshizaki. (MS-DOS LHarc)            */
  450. X/*                                    */
  451. X/*  V0.00  Original                1988.05.23  Y.Tagawa    */
  452. X/*  V0.01  Alpha Version (for 4.2BSD)        1989.05.28  Y.Tagawa    */
  453. X/*  V0.02  Alpha Version Rel.2            1989.05.29  Y.Tagawa    */
  454. X/*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa    */
  455. X/*  V0.03a Fix few bug                          1989.07.03  Y.Tagawa    */
  456. X/*  V0.04  A lot of bugs fixed, strict mode     1990.01.13  Kai Uwe Rommel */
  457. X/*  V1.00  f and t commands, v option added     1990.01.27  Kai Uwe Rommel */
  458. X/*----------------------------------------------------------------------*/
  459. X
  460. X
  461. X#include <stdio.h>
  462. X#include <ctype.h>
  463. X#include <signal.h>
  464. X#include <sys/types.h>
  465. X#include <sys/stat.h>
  466. X#include <prototypes.h>
  467. X
  468. X#ifdef PROF
  469. X#include <profile.h>
  470. X#endif
  471. X
  472. X#define STRICT
  473. X#define FASTCOPY
  474. X
  475. X#ifdef MSDOS
  476. X#include <fcntl.h>
  477. Xextern unsigned char _osmode;
  478. Xextern FILE *popen();
  479. Xextern pclose();
  480. X#define ftruncate chsize
  481. X#define mktemp Mktemp
  482. X#define SYSTIME_HAS_NO_TM
  483. X#define NOBSTRING
  484. X#define SYSNAME (_osmode ? "OS/2" : "MS-DOS")
  485. X#define OUR_EXTEND (_osmode ? EXTEND_OS2 : EXTEND_MSDOS)
  486. X#define FILENAME_LENGTH 128
  487. X#define NULLFILE "nul"
  488. X#define TMP_FILENAME_TEMPLATE "lhXXXXXX"
  489. X#define NOT_COMPATIBLE_MODE
  490. X#define RMODE "rb"
  491. X#define WMODE "wb"
  492. X#else
  493. X#include <sys/file.h>
  494. X#include <time.h>
  495. X#define SYSNAME "UNIX"
  496. X#define ftruncate chsize
  497. X#define OUR_EXTEND EXTEND_UNIX
  498. X#define FILENAME_LENGTH    1024
  499. X#define NULLFILE "/dev/null"
  500. X#define RMODE "r"
  501. X#define WMODE "w"
  502. X#endif
  503. X
  504. X#ifdef SYSTIME_HAS_NO_TM
  505. X/* most of System V,  define SYSTIME_HAS_NO_TM */
  506. X#include <time.h>
  507. X#endif
  508. X
  509. X/* #include <strings.h> */
  510. X#include <string.h>
  511. X#include <sys/select.h>
  512. X#include <sys/fcntl.h>
  513. X/*----------------------------------------------------------------------*/
  514. X/*            DIRECTORY ACCESS STUFF                */
  515. X/*----------------------------------------------------------------------*/
  516. X#ifndef NODIRECTORY
  517. X#ifdef SYSV_SYSTEM_DIR
  518. X
  519. X#include <dirent.h>
  520. X#define DIRENTRY    struct dirent
  521. X#define NAMLEN(p)    strlen (p->d_name)
  522. X
  523. X#else    /* not SYSV_SYSTEM_DIR */
  524. X
  525. X#ifdef NONSYSTEM_DIR_LIBRARY
  526. X#include "lhdir.h"
  527. X#else    /* not NONSYSTEM_DIR_LIBRARY */
  528. X#include <sys/dir.h>
  529. X#endif    /* not NONSYSTEM_DIR_LIBRARY */
  530. X
  531. X#define DIRENTRY    struct direct
  532. X#define NAMLEN(p)    p->d_namlen
  533. X
  534. Xextern DIR *opendir ();
  535. Xextern struct direct *readdir ();
  536. X
  537. X#endif    /* not SYSV_SYSTEM_DIR */
  538. X#endif
  539. X
  540. X/*----------------------------------------------------------------------*/
  541. X/*            FILE ATTRIBUTES                    */
  542. X/*----------------------------------------------------------------------*/
  543. X
  544. X/* If file mode is not compatible between your Machine/OS and
  545. X   LHarc standard UNIX file mode.
  546. X   (See UNIX Manual stat(1), <sys/stat.h>,
  547. X   and/or below UNIX_* difinitions. ) */
  548. X/* #define NOT_COMPATIBLE_MODE */
  549. X
  550. X
  551. X/*----------------------------------------------------------------------*/
  552. X/*            MEMORY FUNCTIONS                 */
  553. X/*----------------------------------------------------------------------*/
  554. X
  555. X#ifdef NOBSTRING
  556. X#ifdef __ANSI__
  557. X#include "mem.h"
  558. X#define bcmp(a,b,n) memcmp ((a),(b),(n))
  559. X#define bcopy(s,d,n) memmove((d),(s),(n))
  560. X#define bzero(d,n) memset((d),0,(n))
  561. X#else    /* not __ANSI__ */
  562. X#include "memory.h"
  563. X#define bcmp(a,b,n) memcmp ((a),(b),(n))
  564. X#define bcopy(s,d,n) memcpy ((d),(s),(n))    /* movmem((s),(d),(n)) */
  565. X#define bzero(d,n) memset((d),0,(n))
  566. X#endif    /* not __ANSI__ */
  567. X#endif    /* NOBSTRING */
  568. X
  569. X
  570. X/*----------------------------------------------------------------------*/
  571. X/*            YOUR CUSTOMIZIES                */
  572. X/*----------------------------------------------------------------------*/
  573. X/* These difinitions are changable to you like. */
  574. X #define ARCHIVENAME_EXTENTION    ".lzh"
  575. X/* #define TMP_FILENAME_TEMPLATE    "/tmp/lhXXXXXX" */
  576. X/* #define BACKUPNAME_EXTENTION        ".BAK"        */
  577. X/* #define MULTIBYTE_CHAR                */
  578. X
  579. X
  580. X
  581. X#define SJC_FIRST_P(c)            \
  582. X  (((unsigned char)(c) >= 0x80) &&    \
  583. X   (((unsigned char)(c) < 0xa0) ||    \
  584. X    ((unsigned char)(c) >= 0xe0) &&    \
  585. X    ((unsigned char)(c) < 0xfd)))
  586. X#define SJC_SECOND_P(c)            \
  587. X  (((unsigned char)(c) >= 0x40) &&    \
  588. X   ((unsigned char)(c) < 0xfd) &&    \
  589. X   ((ungigned char)(c) != 0x7f))
  590. X
  591. X#ifdef MULTIBYTE_CHAR
  592. X#define MULTIBYTE_FIRST_P    SJC_FIRST_P
  593. X#define MULTIBYTE_SECOND_P    SJC_SECOND_P
  594. X#endif
  595. X
  596. X/*----------------------------------------------------------------------*/
  597. X/*            OTHER DIFINITIONS                */
  598. X/*----------------------------------------------------------------------*/
  599. X
  600. X#ifndef SEEK_SET
  601. X#define SEEK_SET    0
  602. X#define SEEK_CUR    1
  603. X#define SEEK_END    2
  604. X#endif
  605. X
  606. X
  607. X/* non-integral functions */
  608. Xextern struct tm *localtime ();
  609. Xextern char *getenv ();
  610. Xextern char *malloc ();
  611. Xextern char *realloc ();
  612. X
  613. Xextern int rson[];
  614. X
  615. X/* external variables */
  616. Xextern int errno;
  617. X
  618. X
  619. X#define    FALSE    0
  620. X#define TRUE    1
  621. Xtypedef int boolean;
  622. X
  623. X
  624. X/*----------------------------------------------------------------------*/
  625. X/*        LHarc FILE DIFINITIONS                    */
  626. X/*----------------------------------------------------------------------*/
  627. X#define METHOD_TYPE_STRAGE    5
  628. X#define LZHUFF0_METHOD        "-lh0-"
  629. X#define LZHUFF1_METHOD        "-lh1-"
  630. X#define LARC4_METHOD        "-lz4-"
  631. X#define LARC5_METHOD        "-lz5-"
  632. X
  633. X#define I_HEADER_SIZE            0
  634. X#define I_HEADER_CHECKSUM        1
  635. X#define I_METHOD            2
  636. X#define I_PACKED_SIZE            7
  637. X#define I_ORIGINAL_SIZE            11
  638. X#define I_LAST_MODIFIED_STAMP        15
  639. X#define I_ATTRIBUTE            19
  640. X#define I_NAME_LENGTH            21
  641. X#define I_NAME                22
  642. X
  643. X#define I_CRC                22 /* + name_length */
  644. X#define I_EXTEND_TYPE            24 /* + name_length */
  645. X#define I_MINOR_VERSION            25 /* + name_length */
  646. X#define I_UNIX_LAST_MODIFIED_STAMP    26 /* + name_length */
  647. X#define I_UNIX_MODE            30 /* + name_length */
  648. X#define I_UNIX_UID            32 /* + name_length */
  649. X#define I_UNIX_GID            34 /* + name_length */
  650. X#define I_UNIX_EXTEND_BOTTOM        36 /* + name_length */
  651. X
  652. X
  653. X
  654. X#define EXTEND_GENERIC  0
  655. X#define EXTEND_UNIX    'U'
  656. X#define EXTEND_MSDOS    'M'
  657. X#define EXTEND_MACOS    'm'
  658. X#define EXTEND_OS9    '9'
  659. X#define EXTEND_OS2    '2'
  660. X#define EXTEND_OS68K    'K'
  661. X#define EXTEND_OS386    '3'
  662. X#define EXTEND_HUMAN    'H'
  663. X#define EXTEND_CPM    'C'
  664. X#define EXTEND_FLEX    'F'
  665. X
  666. X#define GENERIC_ATTRIBUTE        0x20
  667. X#define GENERIC_DIRECTORY_ATTRIBUTE    0x10
  668. X
  669. X#define CURRENT_UNIX_MINOR_VERSION    0x00
  670. X
  671. X
  672. X
  673. Xtypedef struct LzHeader {
  674. X  unsigned char        header_size;
  675. X  char            method[METHOD_TYPE_STRAGE];
  676. X  long            packed_size;
  677. X  long            original_size;
  678. X  long            last_modified_stamp;
  679. X  unsigned short    attribute;
  680. X  char            name[256];
  681. X  unsigned short    crc;
  682. X  boolean        has_crc;
  683. X  unsigned char        extend_type;
  684. X  unsigned char        minor_version;
  685. X  /*  extend_type == EXTEND_UNIX  and convert from other type. */
  686. X  time_t        unix_last_modified_stamp;
  687. X  unsigned short    unix_mode;
  688. X  unsigned short    unix_uid;
  689. X  unsigned short    unix_gid;
  690. X} LzHeader;
  691. X
  692. X#define UNIX_FILE_TYPEMASK    0170000
  693. X#define UNIX_FILE_REGULAR    0100000
  694. X#define UNIX_FILE_DIRECTORY    0040000
  695. X#define UNIX_SETUID        0004000
  696. X#define UNIX_SETGID        0002000
  697. X#define UNIX_STYCKYBIT        0001000
  698. X#define UNIX_OWNER_READ_PERM    0000400
  699. X#define UNIX_OWNER_WRITE_PERM    0000200
  700. X#define UNIX_OWNER_EXEC_PERM    0000100
  701. X#define UNIX_GROUP_READ_PERM    0000040
  702. X#define UNIX_GROUP_WRITE_PERM    0000020
  703. X#define UNIX_GROUP_EXEC_PERM    0000010
  704. X#define UNIX_OTHER_READ_PERM    0000004
  705. X#define UNIX_OTHER_WRITE_PERM    0000002
  706. X#define UNIX_OTHER_EXEC_PERM    0000001
  707. X#define UNIX_RW_RW_RW        0000666
  708. X
  709. X#define LZHEADER_STRAGE        256
  710. X
  711. X/*----------------------------------------------------------------------*/
  712. X/*        PROGRAM                         */
  713. X/*----------------------------------------------------------------------*/
  714. X
  715. X
  716. X#define CMD_UNKNOWN    0
  717. X#define CMD_EXTRACT    1
  718. X#define CMD_APPEND    2
  719. X#define CMD_VIEW    3
  720. X
  721. Xint      cmd = CMD_UNKNOWN;
  722. Xchar     **cmd_filev;
  723. Xint      cmd_filec;
  724. Xchar     *archive_name;
  725. X
  726. Xchar     expanded_archive_name[FILENAME_LENGTH];
  727. Xchar     temporary_name[FILENAME_LENGTH];
  728. Xchar     pager[FILENAME_LENGTH];
  729. X
  730. X
  731. X/* options */
  732. Xboolean    quiet = FALSE;
  733. Xboolean    text_mode = FALSE;
  734. X/*boolean  verbose = FALSE; */
  735. Xboolean  noexec = FALSE; /* debugging option */
  736. Xboolean  force = FALSE;
  737. Xboolean  prof = FALSE;
  738. X
  739. X
  740. X/* view flags */
  741. Xboolean  long_format_listing = FALSE;
  742. X
  743. X/* extract flags */
  744. Xboolean  output_to_test = FALSE;
  745. Xboolean  output_to_stdout = FALSE;
  746. X
  747. X/* append flags */
  748. Xboolean  new_archive = FALSE;
  749. Xboolean  update_if_newer = FALSE;
  750. Xboolean  update_freshen = FALSE;
  751. Xboolean  delete_after_append = FALSE;
  752. Xboolean  delete_from_archive = FALSE;
  753. X
  754. Xboolean  remove_temporary_at_error = FALSE;
  755. X
  756. X
  757. X/*----------------------------------------------------------------------*/
  758. X/* NOTES :    Text File Format                    */
  759. X/*    GENERATOR        NewLine                    */
  760. X/*    [generic]        0D 0A                    */
  761. X/*    [MS-DOS]        0D 0A                    */
  762. X/*    [MacOS]            0D                    */
  763. X/*    [UNIX]            0A                    */
  764. X/*----------------------------------------------------------------------*/
  765. X
  766. Xchar *myname;
  767. X
  768. X
  769. Xvoid userbreak()
  770. X{
  771. X    error("Interrupt.");
  772. X}
  773. X
  774. X
  775. Xmain (argc, argv)
  776. X     int argc;
  777. X     char *argv[];
  778. X{
  779. X  char *p;
  780. X
  781. X  myname = argv[0];
  782. X  signal(SIGINT, userbreak);
  783. X
  784. X#ifdef PROF
  785. X  PROFINIT(PT_USER|PT_USEKP, NULL);
  786. X  PROFCLEAR(PT_USER);
  787. X  PROFON(PT_USER);
  788. X#endif
  789. X
  790. X  if (argc < 3)
  791. X    print_tiny_usage_and_exit ();
  792. X
  793. X  /* commands */
  794. X#ifdef MSDOS
  795. X  switch (tolower(argv[1][0]))
  796. X#else
  797. X  switch (argv[1][0])
  798. X#endif
  799. X    {
  800. X    case 'x':
  801. X    case 'e':
  802. X      cmd = CMD_EXTRACT;
  803. X      break;
  804. X
  805. X    case 't':
  806. X      output_to_test = TRUE;
  807. X      cmd = CMD_EXTRACT;
  808. X      break;
  809. X
  810. X    case 'p':
  811. X      output_to_stdout = TRUE;
  812. X      cmd = CMD_EXTRACT;
  813. X      break;
  814. X
  815. X    case 'c':
  816. X      new_archive = TRUE;
  817. X      cmd = CMD_APPEND;
  818. X      break;
  819. X
  820. X    case 'a':
  821. X      cmd = CMD_APPEND;
  822. X      break;
  823. X
  824. X    case 'd':
  825. X      delete_from_archive = TRUE;
  826. X      cmd = CMD_APPEND;
  827. X      break;
  828. X
  829. X    case 'u':
  830. X      update_if_newer = TRUE;
  831. X      cmd = CMD_APPEND;
  832. X      break;
  833. X
  834. X    case 'f':
  835. X      update_if_newer = update_freshen = TRUE;
  836. X      cmd = CMD_APPEND;
  837. X      break;
  838. X
  839. X    case 'm':
  840. X      delete_after_append = TRUE;
  841. X      cmd = CMD_APPEND;
  842. X      break;
  843. X
  844. X    case 'v':
  845. X      cmd = CMD_VIEW;
  846. X      break;
  847. X
  848. X    case 'l':
  849. X      long_format_listing = TRUE;
  850. X      cmd = CMD_VIEW;
  851. X      break;
  852. X
  853. X    case 'h':
  854. X    default:
  855. X      print_tiny_usage_and_exit ();
  856. X    }
  857. X
  858. X  /* options */
  859. X  p = &argv[1][1];
  860. X  for (p = &argv[1][1]; *p; p++)
  861. X    {
  862. X#ifdef MSDOS
  863. X      switch (tolower(*p))
  864. X#else
  865. X      switch (*p)
  866. X#endif
  867. X    {
  868. X    case 'q':    quiet = TRUE; break;
  869. X    case 'f':    force = TRUE; break;
  870. X/*      case 'p':       prof = TRUE; break; */
  871. X/*      case 'v':       verbose = TRUE; break; */
  872. X        case 'v':       strcpy(pager, p + 1); *(p + 1) = 0; break;
  873. X    case 't':    text_mode = TRUE; break;
  874. X    case 'n':    noexec = TRUE; break;
  875. X
  876. X    default:
  877. X          fprintf (stderr, "unknown option '%c'.\n", *p);
  878. X      exit (1);
  879. X        }
  880. X    }
  881. X
  882. X  /* archive file name */
  883. X  archive_name = argv[2];
  884. X
  885. X  /* target file name */
  886. X  cmd_filec = argc - 3;
  887. X  cmd_filev = argv + 3;
  888. X  sort_files ();
  889. X
  890. X  switch (cmd)
  891. X    {
  892. X    case CMD_EXTRACT:    cmd_extract ();    break;
  893. X    case CMD_APPEND:    cmd_append ();    break;
  894. X    case CMD_VIEW:    cmd_view ();    break;
  895. X    }
  896. X
  897. X#ifdef PROF
  898. X  PROFOFF(PT_USER);
  899. X  PROFDUMP(PT_USER, "profile.out");
  900. X  PROFFREE(PT_USER);
  901. X#endif
  902. X
  903. X  exit (0);
  904. X}
  905. X
  906. Xprint_tiny_usage_and_exit ()
  907. X{
  908. X  printf("\nC-LHarc for %s Version 1.00   (C) 1989-1990 Y.Tagawa, Kai Uwe Rommel\n"
  909. X         "\nUsage: %s {axevlufdmctp}[qnftv] archive_file [files or directories...]\n",
  910. X         SYSNAME, myname);
  911. X  printf("\nCommands:                    Options:\n"
  912. X         "  a   Append                   q   quiet\n"
  913. X         "  x,e EXtract                  n   no execute\n"
  914. X         "  v,l View/List                f   force (over write at extract)\n"
  915. X         "  u   Update                   t   files are TEXT files\n"
  916. X         "  f   Freshen                  v<pager>  use file pager for p command\n"
  917. X         "  d   Delete\n"
  918. X         "  m   Move\n"
  919. X         "  c   re-Construct new archive\n"
  920. X         "  t   Test archive\n"
  921. X         "  p   Print to STDOUT\n");
  922. X  exit (1);
  923. X}
  924. X
  925. Xmessage (title, msg)
  926. X     char *title, *msg;
  927. X{
  928. X  fprintf (stderr, "%s ", myname);
  929. X  if (errno == 0)
  930. X    fprintf (stderr, "%s %s\n", title, msg);
  931. X  else
  932. X    perror (msg);
  933. X}
  934. X
  935. Xwarning (msg)
  936. X     char *msg;
  937. X{
  938. X  message ("Warning:", msg);
  939. X}
  940. X
  941. Xerror (msg)
  942. X     char *msg;
  943. X{
  944. X  message ("Error:", msg);
  945. X
  946. X  if (remove_temporary_at_error)
  947. X  {
  948. X#ifdef MSDOS
  949. X    fcloseall();
  950. X#endif
  951. X    unlink (temporary_name);
  952. X  }
  953. X
  954. X  exit (1);
  955. X}
  956. X
  957. Xchar *writting_filename;
  958. Xchar *reading_filename;
  959. X
  960. Xwrite_error ()
  961. X{
  962. X  error (writting_filename);
  963. X}
  964. X
  965. Xread_error ()
  966. X{
  967. X  error (reading_filename);
  968. X}
  969. X
  970. X
  971. X
  972. X/*----------------------------------------------------------------------*/
  973. X/*                                    */
  974. X/*----------------------------------------------------------------------*/
  975. X
  976. Xboolean expand_archive_name (dst, src)
  977. X     char *dst, *src;
  978. X{
  979. X  register char *p, *dot;
  980. X
  981. X  strcpy (dst, src);
  982. X
  983. X  for (p = dst, dot = (char*)0; *p; p++)
  984. X    if (*p == '.')
  985. X      dot = p;
  986. X    else if (*p == '/' || *p == '\\')
  987. X      dot = (char*)0;
  988. X
  989. X  if (dot)
  990. X    p = dot;
  991. X
  992. X#ifdef ARCHIVENAME_EXTENTION
  993. X  strcpy (p, ARCHIVENAME_EXTENTION);
  994. X#else
  995. X  strcpy (p, ".lzh");
  996. X#endif
  997. X  return (strcmp (dst, src) != 0);
  998. X}
  999. X
  1000. X#ifdef MSDOS
  1001. X#define STRING_COMPARE(a,b) stricmp((a),(b))
  1002. X#else
  1003. X#define STRING_COMPARE(a,b) strcmp((a),(b))
  1004. X#endif
  1005. X
  1006. Xint sort_by_ascii (a, b)
  1007. X     char **a, **b;
  1008. X{
  1009. X  return STRING_COMPARE (*a, *b);
  1010. X}
  1011. X
  1012. Xsort_files ()
  1013. X{
  1014. X  qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
  1015. X}
  1016. X
  1017. X#ifndef MSDOS
  1018. Xchar *strdup (string)
  1019. X     char *string;
  1020. X{
  1021. X  int    len = strlen (string) + 1;
  1022. X  char    *p = malloc (len);
  1023. X  bcopy (string, p, len);
  1024. X  return p;
  1025. X}
  1026. X#endif
  1027. X
  1028. X#ifdef NODIRECTORY
  1029. X/* please need your imprementation */
  1030. Xboolean find_files (name, v_filec, v_filev)
  1031. X     char    *name;
  1032. X     int    *v_filec;
  1033. X     char    ***v_filev;
  1034. X{
  1035. X  return FALSE;            /* DUMMY */
  1036. X}
  1037. X#else
  1038. Xboolean find_files (name, v_filec, v_filev)
  1039. X     char    *name;
  1040. X     int    *v_filec;
  1041. X     char    ***v_filev;
  1042. X{
  1043. X  char        newname[FILENAME_LENGTH];
  1044. X  int         len, n;
  1045. X  DIR        *dirp;
  1046. X  DIRENTRY    *dp;
  1047. X  int           alloc_size = 64; /* any (^_^) */
  1048. X  char        **filev;
  1049. X  int        filec = 0;
  1050. X
  1051. X  if ( strcmp(name, ".") == 0 )
  1052. X    newname[0] = 0;
  1053. X  else
  1054. X    strcpy (newname, name);
  1055. X
  1056. X  len = strlen (newname);
  1057. X  dirp = opendir (name);
  1058. X
  1059. X  if (dirp)
  1060. X    {
  1061. X      filev = (char**)malloc (alloc_size * sizeof(char *));
  1062. X      if (!filev)
  1063. X    error ("not enough memory");
  1064. X
  1065. X      for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
  1066. X    {
  1067. X      n = NAMLEN (dp);
  1068. X          if (
  1069. X#ifndef MSDOS
  1070. X              (dp->d_ino != 0) &&
  1071. X#endif
  1072. X              ((dp->d_name[0] != '.') ||
  1073. X                 ((n != 1) &&
  1074. X                 ((dp->d_name[1] != '.') ||
  1075. X         (n != 2)))) &&            /* exclude '.' and '..' */
  1076. X          (strcmp (dp->d_name, temporary_name) != 0) &&
  1077. X          (strcmp (dp->d_name, archive_name) != 0))
  1078. X        {
  1079. X              if ((len != 0) && (newname[len-1] != '/') && (newname[len-1] != '\\'))
  1080. X                {
  1081. X#ifdef MSDOS
  1082. X                  newname[len] = '\\';
  1083. X#else
  1084. X                  newname[len] = '/';
  1085. X#endif
  1086. X          strncpy (newname+len+1, dp->d_name, n);
  1087. X          newname[len+n+1] = '\0';
  1088. X        }
  1089. X          else
  1090. X        {
  1091. X          strncpy (newname+len, dp->d_name, n);
  1092. X          newname[len+n] = '\0';
  1093. X        }
  1094. X
  1095. X          filev[filec++] = strdup (newname);
  1096. X          if (filec == alloc_size)
  1097. X        {
  1098. X                  alloc_size += 64;
  1099. X                  filev = (char**)realloc (filev, alloc_size * sizeof(char *));
  1100. X        }
  1101. X        }
  1102. X    }
  1103. X      closedir (dirp);
  1104. X    }
  1105. X
  1106. X  *v_filev = filev;
  1107. X  *v_filec = filec;
  1108. X  if (dirp)
  1109. X    {
  1110. X      qsort (filev, filec, sizeof (char*), sort_by_ascii);
  1111. X      return TRUE;
  1112. X    }
  1113. X  else
  1114. X    return FALSE;
  1115. X}
  1116. X#endif
  1117. X
  1118. Xfree_files (filec, filev)
  1119. X     int    filec;
  1120. X     char    **filev;
  1121. X{
  1122. X  int        i;
  1123. X
  1124. X  for (i = 0; i < filec; i ++)
  1125. X    free (filev[i]);
  1126. X
  1127. X  free (filev);
  1128. X}
  1129. X
  1130. X
  1131. X/*----------------------------------------------------------------------*/
  1132. X/*                                    */
  1133. X/*----------------------------------------------------------------------*/
  1134. X
  1135. Xint calc_sum (p, len)
  1136. X     register char *p;
  1137. X     register int len;
  1138. X{
  1139. X  register int sum;
  1140. X
  1141. X  for (sum = 0; len; len--)
  1142. X    sum += *p++;
  1143. X
  1144. X  return sum & 0xff;
  1145. X}
  1146. X
  1147. Xunsigned char *get_ptr;
  1148. X#define setup_get(PTR) get_ptr = (unsigned char*)(PTR)
  1149. X#define get_byte() (*get_ptr++)
  1150. X#define put_ptr    get_ptr
  1151. X#define setup_put(PTR) put_ptr = (unsigned char*)(PTR)
  1152. X#define put_byte(c) *put_ptr++ = (unsigned char)(c)
  1153. X
  1154. Xunsigned short get_word ()
  1155. X{
  1156. X  int b0, b1;
  1157. X
  1158. X  b0 = get_byte ();
  1159. X  b1 = get_byte ();
  1160. X  return (b1 << 8) + b0;
  1161. X}
  1162. X
  1163. Xput_word (v)
  1164. X     unsigned int    v;
  1165. X{
  1166. X  put_byte (v);
  1167. X  put_byte (v >> 8);
  1168. X}
  1169. X
  1170. Xlong get_longword ()
  1171. X{
  1172. X  long b0, b1, b2, b3;
  1173. X
  1174. X  b0 = get_byte ();
  1175. X  b1 = get_byte ();
  1176. X  b2 = get_byte ();
  1177. X  b3 = get_byte ();
  1178. X  return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  1179. X}
  1180. X
  1181. Xput_longword (v)
  1182. X     long v;
  1183. X{
  1184. X  put_byte (v);
  1185. X  put_byte (v >> 8);
  1186. X  put_byte (v >> 16);
  1187. X  put_byte (v >> 24);
  1188. X}
  1189. X
  1190. X
  1191. Xmsdos_to_unix_filename (name, len)
  1192. X     register char *name;
  1193. X     register int len;
  1194. X{
  1195. X  register int i;
  1196. X
  1197. X#ifdef MULTIBYTE_CHAR
  1198. X  for (i = 0; i < len; i ++)
  1199. X    {
  1200. X      if (MULTIBYTE_FIRST_P (name[i]) &&
  1201. X      MULTIBYTE_SECOND_P (name[i+1]))
  1202. X        i ++;
  1203. X#ifndef MSDOS
  1204. X      else if (name[i] == '\\')
  1205. X        name[i] = '/';
  1206. X#endif
  1207. X      else if (isupper (name[i]))
  1208. X    name[i] = tolower (name[i]);
  1209. X    }
  1210. X#else
  1211. X  for (i = 0; i < len; i ++)
  1212. X    {
  1213. X#ifndef MSDOS
  1214. X      if (name[i] == '\\')
  1215. X    name[i] = '/';
  1216. X      else
  1217. X#endif
  1218. X        if (isupper (name[i]))
  1219. X          name[i] = tolower (name[i]);
  1220. X    }
  1221. X#endif
  1222. X}
  1223. X
  1224. Xgeneric_to_unix_filename (name, len)
  1225. X     register char *name;
  1226. X     register int len;
  1227. X{
  1228. X  register int i;
  1229. X  boolean    lower_case_used = FALSE;
  1230. X
  1231. X#ifdef MULTIBYTE_CHAR
  1232. X  for (i = 0; i < len; i ++)
  1233. X    {
  1234. X      if (MULTIBYTE_FIRST_P (name[i]) &&
  1235. X      MULTIBYTE_SECOND_P (name[i+1]))
  1236. X    i ++;
  1237. X      else if (islower (name[i]))
  1238. X    {
  1239. X      lower_case_used = TRUE;
  1240. X      break;
  1241. X    }
  1242. X    }
  1243. X  for (i = 0; i < len; i ++)
  1244. X    {
  1245. X      if (MULTIBYTE_FIRST_P (name[i]) &&
  1246. X      MULTIBYTE_SECOND_P (name[i+1]))
  1247. X        i ++;
  1248. X#ifndef MSDOS
  1249. X      else if (name[i] == '\\')
  1250. X        name[i] = '/';
  1251. X#endif
  1252. X      else if (!lower_case_used && isupper (name[i]))
  1253. X    name[i] = tolower (name[i]);
  1254. X    }
  1255. X#else
  1256. X  for (i = 0; i < len; i ++)
  1257. X    if (islower (name[i]))
  1258. X      {
  1259. X    lower_case_used = TRUE;
  1260. X    break;
  1261. X      }
  1262. X  for (i = 0; i < len; i ++)
  1263. X    {
  1264. X#ifndef MSDOS
  1265. X      if (name[i] == '\\')
  1266. X    name[i] = '/';
  1267. X      else
  1268. X#endif
  1269. X        if (!lower_case_used && isupper (name[i]))
  1270. X          name[i] = tolower (name[i]);
  1271. X    }
  1272. X#endif
  1273. X}
  1274. X
  1275. Xmacos_to_unix_filename (name, len)
  1276. X     register char *name;
  1277. X     register int len;
  1278. X{
  1279. X  register int i;
  1280. X
  1281. X  for (i = 0; i < len; i ++)
  1282. X    {
  1283. X      if (name[i] == ':')
  1284. X    name[i] = '/';
  1285. X      else if (name[i] == '/')
  1286. X    name[i] = ':';
  1287. X    }
  1288. X}
  1289. X
  1290. X/*----------------------------------------------------------------------*/
  1291. X/*                                    */
  1292. X/*    Generic stamp format:                        */
  1293. X/*                                    */
  1294. X/*     31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16        */
  1295. X/*    |<-------- year ------->|<- month ->|<-- day -->|        */
  1296. X/*                                    */
  1297. X/*     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0        */
  1298. X/*    |<--- hour --->|<---- minute --->|<- second*2 ->|        */
  1299. X/*                                    */
  1300. X/*----------------------------------------------------------------------*/
  1301. X
  1302. X
  1303. Xlong gettz ()
  1304. X{
  1305. X#ifdef MSDOS
  1306. X   return timezone;
  1307. X#else
  1308. X   struct timeval    tp;
  1309. X/*   struct timezone    tzp;*/
  1310. X/*   gettimeofday (&tp, &tzp);*/    /* specific to 4.3BSD */
  1311. X/* return (tzp.tz_minuteswest * 60 + (tzp.tz_dsttime != 0 ? 60L * 60L : 0));*/
  1312. X   return (60);
  1313. X#endif
  1314. X}
  1315. X
  1316. X#ifdef NOT_USED
  1317. Xstruct tm *msdos_to_unix_stamp_tm (a)
  1318. X     long a;
  1319. X{
  1320. X  static struct tm t;
  1321. X  t.tm_sec    = ( a          & 0x1f) * 2;
  1322. X  t.tm_min    =  (a >>    5) & 0x3f;
  1323. X  t.tm_hour    =  (a >>   11) & 0x1f;
  1324. X  t.tm_mday    =  (a >>   16) & 0x1f;
  1325. X  t.tm_mon    =  (a >> 16+5) & 0x0f - 1;
  1326. X  t.tm_year    = ((a >> 16+9) & 0x7f) + 80;
  1327. X  return &t;
  1328. X}
  1329. X#endif
  1330. X
  1331. Xtime_t generic_to_unix_stamp (t)
  1332. X     long t;
  1333. X{
  1334. X  struct tm tm;
  1335. X  long longtime;
  1336. X  static unsigned int dsboy[12] =
  1337. X    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  1338. X  unsigned long days;
  1339. X
  1340. X  tm.tm_year =  ((int)(t >> 25) & 0x7f) + 80;
  1341. X  tm.tm_mon  =  ((int)(t >> 21) & 0x0f) - 1;     /* 0..11 means Jan..Dec */
  1342. X  tm.tm_mday =  (int)(t >> 16) & 0x1f;         /* 1..31 means 1st,...31st */
  1343. X
  1344. X  tm.tm_hour =  ((int)t >> 11) & 0x1f;
  1345. X  tm.tm_min  =  ((int)t >> 5)  & 0x3f;
  1346. X  tm.tm_sec  =  ((int)t        & 0x1f) * 2;
  1347. X
  1348. X#ifdef MSDOS
  1349. X  longtime = mktime(&tm);
  1350. X#else
  1351. X                                      /* Calculate days since 1970.01.01 */
  1352. X  days = (365 * (tm.tm_year - 70) +   /* days due to whole years */
  1353. X          (tm.tm_year - 70 + 1) / 4 + /* days due to leap years */
  1354. X          dsboy[tm.tm_mon] +          /* days since beginning of this year */
  1355. X          tm.tm_mday-1);              /* days since beginning of month */
  1356. X
  1357. X  if ((tm.tm_year % 4 == 0) &&
  1358. X      (tm.tm_year % 400 != 0) &&
  1359. X      (tm.tm_mon >= 2))         /* if this is a leap year and month */
  1360. X    days++;            /* is March or later, add a day */
  1361. X
  1362. X  /* Knowing the days, we can find seconds */
  1363. X  longtime = (((days * 24) + tm.tm_hour) * 60 + tm.tm_min) * 60 + tm.tm_sec;
  1364. X  longtime += gettz ();      /* adjust for timezone */
  1365. X#endif
  1366. X
  1367. X  /* special case:  if MSDOS format date and time were zero, then we set
  1368. X     time to be zero here too. */
  1369. X  if (t == 0)
  1370. X    longtime = 0;
  1371. X
  1372. X  /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
  1373. X  return (time_t)longtime;
  1374. X}
  1375. X
  1376. Xlong unix_to_generic_stamp (t)
  1377. X     time_t t;
  1378. X{
  1379. X  struct tm *tm = localtime (&t);
  1380. X  unsigned long stamp;
  1381. X
  1382. X  stamp =  ( ((long)(tm->tm_year - 80)) << 25 );
  1383. X  stamp += ( ((long)(tm->tm_mon + 1))   << 21 );
  1384. X  stamp += ( ((long)(tm->tm_mday))      << 16 );
  1385. X  stamp += ( ((long)(tm->tm_hour))      << 11 );
  1386. X  stamp += ( ((long)(tm->tm_min))       << 5 );
  1387. X  stamp += ( ((long)(tm->tm_sec))       >> 1 );
  1388. X
  1389. X  return stamp;
  1390. X}
  1391. X
  1392. X/*----------------------------------------------------------------------*/
  1393. X/*                                    */
  1394. X/*----------------------------------------------------------------------*/
  1395. X
  1396. Xboolean get_header (fp, hdr)
  1397. X     FILE *fp;
  1398. X     register LzHeader *hdr;
  1399. X{
  1400. X  int        header_size;
  1401. X  int        name_length;
  1402. X  char        data[LZHEADER_STRAGE];
  1403. X  int        checksum;
  1404. X  int        i;
  1405. X
  1406. X  bzero (hdr, sizeof (LzHeader));
  1407. X
  1408. X  if (((header_size = getc (fp)) == EOF) || (header_size == 0))
  1409. X    {
  1410. X      return FALSE;        /* finish */
  1411. X    }
  1412. X
  1413. X  if (fread (data + I_HEADER_CHECKSUM,
  1414. X          sizeof (char), header_size + 1, fp) < header_size + 1)
  1415. X    {
  1416. X      error ("Invalid header (LHarc file ?)\a");
  1417. X      return FALSE;        /* finish */
  1418. X    }
  1419. X
  1420. X  setup_get (data + I_HEADER_CHECKSUM);
  1421. X  checksum = calc_sum (data + I_METHOD, header_size);
  1422. X  if (get_byte () != checksum)
  1423. X    warning ("Checksum error (LHarc file?)\a");
  1424. X
  1425. X  hdr->header_size = header_size;
  1426. X  bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1427. X#ifdef OLD
  1428. X  if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  1429. X      (bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  1430. X      (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  1431. X      (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0))
  1432. X    {
  1433. X      warning ("Unknown method (LHarc file ?)");
  1434. X      return FALSE;        /* invalid method */
  1435. X    }
  1436. X#endif
  1437. X  setup_get (data + I_PACKED_SIZE);
  1438. X  hdr->packed_size    = get_longword ();
  1439. X  hdr->original_size    = get_longword ();
  1440. X  hdr->last_modified_stamp = get_longword ();
  1441. X  hdr->attribute    = get_word ();
  1442. X  name_length        = get_byte ();
  1443. X  for (i = 0; i < name_length; i ++)
  1444. X    hdr->name[i] =(char)get_byte ();
  1445. X  hdr->name[name_length] = '\0';
  1446. X
  1447. X  /* defaults for other type */
  1448. X  hdr->unix_mode    = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
  1449. X  hdr->unix_gid     = 0;
  1450. X  hdr->unix_uid        = 0;
  1451. X
  1452. X  if (header_size - name_length >= 24)
  1453. X    {                /* EXTEND FORMAT */
  1454. X      hdr->crc                = get_word ();
  1455. X      hdr->extend_type            = get_byte ();
  1456. X      hdr->minor_version        = get_byte ();
  1457. X      hdr->has_crc = TRUE;
  1458. X    }
  1459. X  else if (header_size - name_length == 22)
  1460. X    {                /* Generic with CRC */
  1461. X      hdr->crc                = get_word ();
  1462. X      hdr->extend_type            = EXTEND_GENERIC;
  1463. X      hdr->has_crc = TRUE;
  1464. X    }
  1465. X  else if (header_size - name_length == 20)
  1466. X    {                /* Generic no CRC */
  1467. X      hdr->extend_type            = EXTEND_GENERIC;
  1468. X      hdr->has_crc = FALSE;
  1469. X    }
  1470. X  else
  1471. X    {
  1472. X      warning ("Unknown header (LHarc file ?)");
  1473. X      return FALSE;
  1474. X    }
  1475. X
  1476. X  switch (hdr->extend_type)
  1477. X    {
  1478. X    case EXTEND_MSDOS:
  1479. X      msdos_to_unix_filename (hdr->name, name_length);
  1480. X      hdr->unix_last_modified_stamp    =
  1481. X    generic_to_unix_stamp (hdr->last_modified_stamp);
  1482. X      break;
  1483. X
  1484. X    case EXTEND_UNIX:
  1485. X      hdr->unix_last_modified_stamp    = (time_t)get_longword ();
  1486. X      hdr->unix_mode            = get_word ();
  1487. X      hdr->unix_uid            = get_word ();
  1488. X      hdr->unix_gid            = get_word ();
  1489. X      break;
  1490. X
  1491. X    case EXTEND_MACOS:
  1492. X      macos_to_unix_filename (hdr->name, name_length);
  1493. X      hdr->unix_last_modified_stamp    =
  1494. X    generic_to_unix_stamp (hdr->last_modified_stamp);
  1495. X      break;
  1496. X
  1497. X    default:
  1498. X      generic_to_unix_filename (hdr->name, name_length);
  1499. X      hdr->unix_last_modified_stamp    =
  1500. X    generic_to_unix_stamp (hdr->last_modified_stamp);
  1501. X    }
  1502. X
  1503. X  return TRUE;
  1504. X}
  1505. X
  1506. Xinit_header (name, v_stat, hdr)
  1507. X     char *name;
  1508. X     struct stat *v_stat;
  1509. X     LzHeader *hdr;
  1510. X{
  1511. X  bcopy (LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1512. X  hdr->packed_size        = 0;
  1513. X  hdr->original_size        = v_stat->st_size;
  1514. X  hdr->last_modified_stamp      = unix_to_generic_stamp (v_stat->st_mtime);
  1515. X#ifdef MSDOS
  1516. X  getfilemode(name, &(hdr->attribute));
  1517. X#else
  1518. X  hdr->attribute                = GENERIC_ATTRIBUTE;
  1519. X#endif
  1520. X  strcpy (hdr->name, name);
  1521. X  hdr->crc            = 0x0000;
  1522. X  hdr->extend_type              = OUR_EXTEND;
  1523. X  hdr->unix_last_modified_stamp    = v_stat->st_mtime;
  1524. X                /* 00:00:00 since JAN.1.1970 */
  1525. X#ifdef NOT_COMPATIBLE_MODE
  1526. X  hdr->unix_mode        = v_stat->st_mode;
  1527. X#else
  1528. X  hdr->unix_mode        = v_stat->st_mode;
  1529. X#endif
  1530. X
  1531. X  hdr->unix_uid            = v_stat->st_uid;
  1532. X  hdr->unix_gid            = v_stat->st_gid;
  1533. X
  1534. X  if ((v_stat->st_mode & S_IFMT) == S_IFDIR)
  1535. X    {
  1536. X      bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1537. X      hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
  1538. X      hdr->original_size = 0;
  1539. X      strcat (hdr->name, "/");
  1540. X    }
  1541. X}
  1542. X
  1543. X/* Write only unix extended header. */
  1544. Xwrite_header (nafp, hdr)
  1545. X     FILE *nafp;
  1546. X     LzHeader *hdr;
  1547. X{
  1548. X  int        header_size;
  1549. X  int        name_length;
  1550. X  char          data[LZHEADER_STRAGE], *ptr;
  1551. X  int           cnt;
  1552. X
  1553. X  bzero (data, LZHEADER_STRAGE);
  1554. X  bcopy (hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
  1555. X  setup_put (data + I_PACKED_SIZE);
  1556. X  put_longword (hdr->packed_size);
  1557. X  put_longword (hdr->original_size);
  1558. X  put_longword (hdr->last_modified_stamp);
  1559. X  put_word (hdr->attribute);
  1560. X  
  1561. X#ifdef STRICT
  1562. X
  1563. X  if ( hdr->name[1] == ':' )
  1564. X  {
  1565. X    name_length = strlen(hdr->name + 2);
  1566. X    put_byte (name_length);
  1567. X    bcopy (hdr->name + 2, data + I_NAME, name_length);
  1568. X  }
  1569. X  else
  1570. X  {
  1571. X    name_length = strlen(hdr->name);
  1572. X    put_byte (name_length);
  1573. X    bcopy (hdr->name, data + I_NAME, name_length);
  1574. X  }
  1575. X  
  1576. X  for ( ptr = data + I_NAME, cnt = 0; cnt < name_length; ptr++, cnt++ )
  1577. X  {
  1578. X    *ptr = toupper(*ptr);
  1579. X
  1580. X    if ( *ptr == '/' )
  1581. X      *ptr = '\\';
  1582. X  }
  1583. X#else
  1584. X  name_length = strlen (hdr->name);
  1585. X  put_byte (name_length);
  1586. X  bcopy (hdr->name, data + I_NAME, name_length);
  1587. X#endif
  1588. X  
  1589. X  setup_put (data + I_NAME + name_length);
  1590. X  put_word (hdr->crc);
  1591. X#ifdef STRICT
  1592. X  header_size = I_EXTEND_TYPE - 2 + name_length;
  1593. X#else
  1594. X  put_byte (OUR_EXTEND);
  1595. X  put_byte (CURRENT_UNIX_MINOR_VERSION);
  1596. X  put_longword ((long)hdr->unix_last_modified_stamp);
  1597. X  put_word (hdr->unix_mode);
  1598. X  put_word (hdr->unix_uid);
  1599. X  put_word (hdr->unix_gid);
  1600. X  header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
  1601. X#endif
  1602. X  data[I_HEADER_SIZE] = header_size;
  1603. X  data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
  1604. X
  1605. X  if (fwrite (data, sizeof (char), header_size + 2, nafp) == NULL)
  1606. X    error ("cannot write to temporary file");
  1607. X}
  1608. X
  1609. Xboolean archive_is_msdos_sfx1 (name)
  1610. X     char *name;
  1611. X{
  1612. X  int    len = strlen (name);
  1613. X  return ((len >= 4) &&
  1614. X      (strcmp (name + len - 4, ".com") == 0 ||
  1615. X       strcmp (name + len - 4, ".exe") == 0));
  1616. X}
  1617. X
  1618. Xboolean skip_msdos_sfx1_code (fp)
  1619. X     FILE *fp;
  1620. X{
  1621. X  unsigned char buffer[2048];
  1622. X  unsigned char *p, *q;
  1623. X  int    n;
  1624. X
  1625. X  n = fread (buffer, sizeof (char), 2048, fp);
  1626. X
  1627. X  for (p = buffer + 2, q = buffer + n - 5; p < q; p ++)
  1628. X    {
  1629. X      /* found "-l??-" keyword (as METHOD type string) */
  1630. X      if (p[0] == '-' && p[1] == 'l' && p[4] == '-')
  1631. X    {
  1632. X      /* size and checksum validate check */
  1633. X      if (p[-2] > 20 && p[-1] == calc_sum (p, p[-2]))
  1634. X        {
  1635. X              fseek (fp, (long) ((p - 2) - buffer) - n, SEEK_CUR);
  1636. X          return TRUE;
  1637. X        }
  1638. X    }
  1639. X    }
  1640. X
  1641. X  fseek (fp, (long) -n, SEEK_CUR);
  1642. X  return FALSE;
  1643. X}
  1644. X
  1645. X
  1646. X/*----------------------------------------------------------------------*/
  1647. X/*                                    */
  1648. X/*----------------------------------------------------------------------*/
  1649. X
  1650. Xmake_tmp_name (original, name)
  1651. X     char *original;
  1652. X     char *name;
  1653. X{
  1654. X#ifdef TMP_FILENAME_TEMPLATE
  1655. X  /* "/tmp/lhXXXXXX" etc. */
  1656. X  strcpy (name, TMP_FILENAME_TEMPLATE);
  1657. X#else
  1658. X  char *p, *s;
  1659. X
  1660. X  strcpy (name, original);
  1661. X  for (p = name, s = (char*)0; *p; p++)
  1662. X    if (*p == '/' || *p == '\\')
  1663. X      s = p;
  1664. X
  1665. X  strcpy ((s ? s+1 : name), "lhXXXXXX");
  1666. X#endif
  1667. X
  1668. X  mktemp (name);
  1669. X}
  1670. X
  1671. Xmake_backup_name (name, orginal)
  1672. X     char *name;
  1673. X     char *orginal;
  1674. X{
  1675. X  register char *p, *dot;
  1676. X
  1677. X  strcpy (name, orginal);
  1678. X  for (p = name, dot = (char*)0; *p; p ++)
  1679. X    {
  1680. X      if (*p == '.')
  1681. X    dot = p;
  1682. X      else if (*p == '/' || *p == '\\')
  1683. X    dot = (char*)0;
  1684. X    }
  1685. X
  1686. X  if (dot)
  1687. X    p = dot;
  1688. X
  1689. X#ifdef BACKUPNAME_EXTENTION
  1690. X  strcpy (p, BACKUPNAME_EXTENTION)
  1691. X#else
  1692. X  strcpy (p, ".bak");
  1693. X#endif
  1694. X}
  1695. X
  1696. Xmake_standard_archive_name (name, orginal)
  1697. X     char *name;
  1698. X     char *orginal;
  1699. X{
  1700. X  register char *p, *dot;
  1701. X
  1702. X  strcpy (name, orginal);
  1703. X  for (p = name, dot = (char*)0; *p; p ++)
  1704. X    {
  1705. X      if (*p == '.')
  1706. X    dot = p;
  1707. X      else if (*p == '/' || *p == '\\')
  1708. X    dot = (char*)0;
  1709. X    }
  1710. X
  1711. X  if (dot)
  1712. X    p = dot;
  1713. X
  1714. X#ifdef ARCHIVENAME_EXTENTION
  1715. X  strcpy (p, ARCHIVENAME_EXTENTION);
  1716. X#else
  1717. X  strcpy (p, ".lzh");
  1718. X#endif
  1719. X}
  1720. X
  1721. X/*----------------------------------------------------------------------*/
  1722. X/*                                    */
  1723. X/*----------------------------------------------------------------------*/
  1724. X
  1725. X
  1726. Xboolean need_file (name)
  1727. X     char *name;
  1728. X{
  1729. X  int    i;
  1730. X
  1731. X  if (cmd_filec == 0)
  1732. X    return TRUE;
  1733. X
  1734. X  for (i = 0; i < cmd_filec; i ++)
  1735. X    {
  1736. X      if (STRING_COMPARE (cmd_filev[i], name) == 0)
  1737. X    return TRUE;
  1738. X    }
  1739. X
  1740. X  return FALSE;
  1741. X}
  1742. X
  1743. XFILE *xfopen (name, mode)
  1744. X     char *name, *mode;
  1745. X{
  1746. X  FILE *fp;
  1747. X
  1748. X  if ((fp = fopen (name, mode)) == NULL)
  1749. X    error (name);
  1750. X
  1751. X  return fp;
  1752. X}
  1753. X
  1754. X
  1755. X/*----------------------------------------------------------------------*/
  1756. X/*        Listing Stuff                        */
  1757. X/*----------------------------------------------------------------------*/
  1758. X
  1759. X/* need 14 or 22 (when long_format_listing is TRUE) column spaces */
  1760. Xprint_size (packed_size, original_size)
  1761. X     long packed_size, original_size;
  1762. X{
  1763. X  if (long_format_listing)
  1764. X    printf ("%7ld ", packed_size);
  1765. X
  1766. X  printf ("%7ld ", original_size);
  1767. X
  1768. X  if (original_size == 0L)
  1769. X    printf ("******");
  1770. X  else
  1771. X    printf ("%3d.%1d%%",
  1772. X        (int)((packed_size * 100L) / original_size),
  1773. X        (int)((packed_size * 1000L) / original_size) % 10);
  1774. X}
  1775. X
  1776. X/* need 12 or 17 (when long_format_listing is TRUE) column spaces */
  1777. Xprint_stamp (t)
  1778. X     time_t t;
  1779. X{
  1780. X  static boolean    got_now = FALSE;
  1781. X  static time_t        now;
  1782. X  static unsigned int    threshold;
  1783. X  static char   t_month[12*3+1] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  1784. X  struct tm        *p;
  1785. X
  1786. X  if (t == 0)
  1787. X    {
  1788. X      if (long_format_listing)
  1789. X    printf ("                 "); /* 17 spaces */
  1790. X      else
  1791. X    printf ("            ");    /* 12 spaces */
  1792. X
  1793. X      return;
  1794. X    }
  1795. X
  1796. X  if (!got_now)
  1797. X    {
  1798. X      time (&now);
  1799. X      p = localtime (&now);
  1800. X      threshold = p->tm_year * 12 + p->tm_mon - 6;
  1801. X      got_now = TRUE;
  1802. X    }
  1803. X
  1804. X  p = localtime (&t);
  1805. X
  1806. X  if (long_format_listing)
  1807. X    printf ("%.3s %2d %02d:%02d %04d",
  1808. X        &t_month[p->tm_mon * 3], p->tm_mday,
  1809. X        p->tm_hour, p->tm_min, p->tm_year + 1900);
  1810. X  else
  1811. X    if (p->tm_year * 12 + p->tm_mon > threshold)
  1812. X      printf ("%.3s %2d %02d:%02d",
  1813. X          &t_month[p->tm_mon * 3], p->tm_mday, p->tm_hour, p->tm_min);
  1814. X    else
  1815. X      printf ("%.3s %2d  %04d",
  1816. X          &t_month[p->tm_mon * 3], p->tm_mday, p->tm_year + 1900);
  1817. X}
  1818. X
  1819. Xprint_bar ()
  1820. X{
  1821. X  /* 17+1+(0 or 7+1)+7+1+6+1+(0 or 1+4)+(12 or 17)+1+20 */
  1822. X  /*       12345678901234567_  1234567_123456  _123456789012   1234      */
  1823. X  if (long_format_listing)
  1824. X#ifdef STRICT
  1825. X    printf ("------- ------- ------ ---- ----------------- -------------\n");
  1826. X#else
  1827. X    printf ("----------------- ------- ------- ------ ---- ----------------- -------------\n");
  1828. X#endif
  1829. X  else
  1830. X#ifdef STRICT
  1831. X    printf ("------- ------ ------------ --------------------\n");
  1832. X#else
  1833. X    printf ("----------------- ------- ------ ------------ --------------------\n");
  1834. X#endif
  1835. X}
  1836. X
  1837. X
  1838. X/*
  1839. X  view
  1840. X */
  1841. Xcmd_view ()
  1842. X{
  1843. X  FILE        *fp;
  1844. X  LzHeader    hdr;
  1845. X  register char    *p;
  1846. X  long        a_packed_size = 0L;
  1847. X  long        a_original_size = 0L;
  1848. X  int        n_files = 0;
  1849. X  struct stat    v_stat;
  1850. X
  1851. X  if ((fp = fopen (archive_name, RMODE)) == NULL)
  1852. X    if (!expand_archive_name (expanded_archive_name, archive_name))
  1853. X      error (archive_name);
  1854. X    else
  1855. X      {
  1856. X    errno = 0;
  1857. X        fp = xfopen (expanded_archive_name, RMODE);
  1858. X    archive_name = expanded_archive_name;
  1859. X      }
  1860. X
  1861. X  if (archive_is_msdos_sfx1 (archive_name))
  1862. X    {
  1863. X      skip_msdos_sfx1_code (fp);
  1864. X    }
  1865. X
  1866. X  if (!quiet)
  1867. X    {
  1868. X      /*       12345678901234567_  1234567_123456  _  123456789012  1234 */
  1869. X#ifdef STRICT
  1870. X      printf ("%s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
  1871. X#else
  1872. X      printf (" PERMSSN  UID GID %s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
  1873. X#endif
  1874. X          long_format_listing ? " PACKED " : "", /* 8,0 */
  1875. X          long_format_listing ? "  CRC" : "", /* 5,0 */
  1876. X          long_format_listing ? "  " : "", /* 2,0 */
  1877. X          long_format_listing ? "   " : ""); /* 3,0 */
  1878. X      print_bar ();
  1879. X    }
  1880. X
  1881. X  while (get_header (fp, &hdr))
  1882. X    {
  1883. X      if (need_file (hdr.name))
  1884. X    {
  1885. X      if (hdr.extend_type == EXTEND_UNIX)
  1886. X            {
  1887. X#ifndef STRICT
  1888. X              printf ("%c%c%c%c%c%c%c%c%c%4d/%-4d",
  1889. X          ((hdr.unix_mode & UNIX_OWNER_READ_PERM)  ? 'r' : '-'),
  1890. X          ((hdr.unix_mode & UNIX_OWNER_WRITE_PERM) ? 'w' : '-'),
  1891. X          ((hdr.unix_mode & UNIX_OWNER_EXEC_PERM)  ? 'x' : '-'),
  1892. X          ((hdr.unix_mode & UNIX_GROUP_READ_PERM)  ? 'r' : '-'),
  1893. X          ((hdr.unix_mode & UNIX_GROUP_WRITE_PERM) ? 'w' : '-'),
  1894. X          ((hdr.unix_mode & UNIX_GROUP_EXEC_PERM)  ? 'x' : '-'),
  1895. X          ((hdr.unix_mode & UNIX_OTHER_READ_PERM)  ? 'r' : '-'),
  1896. X          ((hdr.unix_mode & UNIX_OTHER_WRITE_PERM) ? 'w' : '-'),
  1897. X          ((hdr.unix_mode & UNIX_OTHER_EXEC_PERM)  ? 'x' : '-'),
  1898. X          hdr.unix_uid, hdr.unix_gid);
  1899. X#endif
  1900. X        }
  1901. X      else
  1902. X        {
  1903. X          switch (hdr.extend_type)
  1904. X        {            /* max 18 characters */
  1905. X                case EXTEND_GENERIC:    p = "[Generic]"; break;
  1906. X
  1907. X        case EXTEND_CPM:    p = "[CP/M]"; break;
  1908. X
  1909. X          /* OS-9 and FLEX's CPU is MC-6809. I like it. :-)  */
  1910. X        case EXTEND_FLEX:    p = "[FLEX]"; break;
  1911. X
  1912. X        case EXTEND_OS9:    p = "[OS-9]"; break;
  1913. X
  1914. X          /* I guessed from this ID.  Is this right? */
  1915. X        case EXTEND_OS68K:    p = "[OS-9/68K]"; break;
  1916. X
  1917. X        case EXTEND_MSDOS:    p = "[MS-DOS]"; break;
  1918. X
  1919. X          /* I have Macintosh. :-)  */
  1920. X        case EXTEND_MACOS:    p = "[Mac OS]"; break;
  1921. X
  1922. X        case EXTEND_OS2:    p = "[OS/2]"; break;
  1923. X
  1924. X        case EXTEND_HUMAN:    p = "[Human68K]"; break;
  1925. X
  1926. X        case EXTEND_OS386:    p = "[OS-386]"; break;
  1927. X
  1928. X#ifdef EXTEND_TOWNSOS
  1929. X          /* This ID isn't fixed */
  1930. X        case EXTEND_TOWNSOS:    p = "[TownsOS]"; break;
  1931. X#endif
  1932. X
  1933. X          /* Ouch!  Please customize it's ID.  */
  1934. X                default:                p = "[Unknown]"; break;
  1935. X                }
  1936. X#ifndef STRICT
  1937. X              printf ("%-18.18s", p);
  1938. X#endif
  1939. X        }
  1940. X
  1941. X      print_size (hdr.packed_size, hdr.original_size);
  1942. X
  1943. X      if (long_format_listing)
  1944. X        if (hdr.has_crc)
  1945. X          printf (" %04x", hdr.crc);
  1946. X        else
  1947. X          printf (" ****");
  1948. X
  1949. X      printf (" ");
  1950. X      print_stamp (hdr.unix_last_modified_stamp);
  1951. X      printf (" %s\n", hdr.name);
  1952. X      n_files ++;
  1953. X      a_packed_size += hdr.packed_size;
  1954. X      a_original_size += hdr.original_size;
  1955. X    }
  1956. X      fseek (fp, hdr.packed_size, SEEK_CUR);
  1957. X    }
  1958. X
  1959. X  fclose (fp);
  1960. X  if (!quiet)
  1961. X    {
  1962. X      print_bar ();
  1963. X
  1964. X#ifndef STRICT
  1965. X      printf (" Total %4d file%c ",
  1966. X          n_files, (n_files == 1) ? ' ' : 's');
  1967. X#endif
  1968. X      print_size (a_packed_size, a_original_size);
  1969. X      printf (" ");
  1970. X
  1971. X      if (long_format_listing)
  1972. X    printf ("     ");
  1973. X
  1974. X      if (stat (archive_name, &v_stat) < 0)
  1975. X    print_stamp ((time_t)0);
  1976. X      else
  1977. X    print_stamp (v_stat.st_mtime);
  1978. X
  1979. X#ifdef STRICT
  1980. X      printf (" %4d file%c ",
  1981. X          n_files, (n_files == 1) ? ' ' : 's');
  1982. X#endif
  1983. X      printf ("\n");
  1984. X    }
  1985. X
  1986. X  return;
  1987. X}
  1988. X
  1989. X
  1990. Xboolean make_parent_path (name)
  1991. X     char *name;
  1992. X{
  1993. X  char        path[FILENAME_LENGTH];
  1994. X  struct stat    v_stat;
  1995. X  register char    *p;
  1996. X
  1997. X /* make parent directory name into PATH for recursive call */
  1998. X  strcpy (path, name);
  1999. X  for (p = path + strlen (path); p > path; p --)
  2000. X    if (p[-1] == '/' || p[-1] == '\\')
  2001. X      {
  2002. X    p[-1] = '\0';
  2003. X    break;
  2004. X      }
  2005. X
  2006. X  if (p == path)
  2007. X    return FALSE;        /* no more parent. */
  2008. X
  2009. X  if (stat (path, &v_stat) >= 0)
  2010. X    {
  2011. X      if ((v_stat.st_mode & S_IFMT) != S_IFDIR)
  2012. X    return FALSE;        /* already exist. but it isn't directory. */
  2013. X      return TRUE;        /* already exist its directory. */
  2014. X    }
  2015. X
  2016. X  errno = 0;
  2017. X
  2018. X  if (!quiet)
  2019. X    message ("Making Directory", path);
  2020. X
  2021. X  if (mkdir (path, 0777) >= 0)    /* try */
  2022. X    return TRUE;        /* successful done. */
  2023. X
  2024. X  errno = 0;
  2025. X
  2026. X  if (!make_parent_path (path))
  2027. X    return FALSE;
  2028. X
  2029. X  if (mkdir (path, 0777) < 0)        /* try again */
  2030. X    return FALSE;
  2031. X
  2032. X  return TRUE;
  2033. X}
  2034. X
  2035. XFILE *open_with_make_path (name)
  2036. X     char *name;
  2037. X{
  2038. X  FILE        *fp;
  2039. X  struct stat    v_stat;
  2040. X  char        buffer[1024];
  2041. X
  2042. X  if (stat (name, &v_stat) >= 0)
  2043. X    {
  2044. X      if ((v_stat.st_mode & S_IFMT) != S_IFREG)
  2045. X    return NULL;
  2046. X
  2047. X      if (!force)
  2048. X    {
  2049. X      for (;;)
  2050. X        {
  2051. X          fprintf (stderr, "%s OverWrite ?(Yes/No/All) ", name);
  2052. X          fflush (stderr);
  2053. X          gets (buffer);
  2054. X          if (buffer[0] == 'N' || buffer[0] == 'n')
  2055. X        return NULL;
  2056. X          if (buffer[0] == 'Y' || buffer[0] == 'y')
  2057. X        break;
  2058. X          if (buffer[0] == 'A' || buffer[0] == 'a')
  2059. X        {
  2060. X          force = TRUE;
  2061. X          break;
  2062. X        }
  2063. X        }
  2064. X    }
  2065. X    }
  2066. X
  2067. X  fp = fopen (name, WMODE);
  2068. X  if (!fp)
  2069. X    {
  2070. X      errno = 0;
  2071. X      if (!make_parent_path (name))
  2072. X    return NULL;
  2073. X
  2074. X      fp = fopen (name, WMODE);
  2075. X      if (!fp)
  2076. X        message ("Error:", name);
  2077. X    }
  2078. X  return fp;
  2079. X}
  2080. X
  2081. X#ifdef MSDOS
  2082. Xvoid dosname(char *name)
  2083. X{
  2084. X  char *ptr, *first = NULL, *last = NULL;
  2085. X  char temp[8];
  2086. X
  2087. X  for ( ptr = strchr(name, 0); ptr >= name; ptr-- )
  2088. X    if ( *ptr == '.' )
  2089. X    {
  2090. X      if ( last == NULL )
  2091. X        last = ptr;
  2092. X    }
  2093. X    else if ( (*ptr == '/') || (*ptr == '\\') )
  2094. X    {
  2095. X      first = ptr + 1;
  2096. X      break;
  2097. X    }
  2098. X
  2099. X  if ( first == NULL )
  2100. X    first = name;
  2101. X  if ( last == NULL )
  2102. X    last = strchr(name, 0);
  2103. X
  2104. X  for ( ptr = first; ptr < last; ptr++ )
  2105. X    if ( *ptr == '.' )
  2106. X      *ptr = '_';
  2107. X
  2108. X  if ( strlen(last) > 4 )
  2109. X    last[4] = 0;
  2110. X
  2111. X  if ( last - first > 8 )
  2112. X  {
  2113. X    strcpy(temp, last);
  2114. X    strcpy(first + 8, last);
  2115. X  }
  2116. X}
  2117. X#endif
  2118. X
  2119. Xextern int decode_lzhuf (), decode_larc ();
  2120. Xextern int decode_stored_crc (), decode_stored_nocrc ();
  2121. X
  2122. Xextract_one (fp, hdr)
  2123. X     FILE *fp;
  2124. X     LzHeader *hdr;
  2125. X{
  2126. X  FILE        *ofp;        /* output file */
  2127. X  char        name[1024];
  2128. X  time_t    utimebuf[2];
  2129. X  int        crc;
  2130. X  int        (*decode_proc)(); /* (ifp,ofp,original_size,name) */
  2131. X  int        save_quiet;
  2132. X
  2133. X  strcpy (name, hdr->name);
  2134. X  if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  2135. X    {
  2136. X      if (bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) == 0)
  2137. X    decode_proc = decode_lzhuf;
  2138. X      else if ((bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) == 0) ||
  2139. X           (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) == 0))
  2140. X    decode_proc = (hdr->has_crc) ? decode_stored_crc : decode_stored_nocrc;
  2141. X      else if (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) == 0)
  2142. X    decode_proc = decode_larc;
  2143. X      else
  2144. X        message ("Error:", "Sorry, Cannot Extract this method.");
  2145. X
  2146. X      reading_filename = archive_name;
  2147. X      writting_filename = name;
  2148. X      if (output_to_stdout)
  2149. X    {
  2150. X          if (!quiet)
  2151. X            printf ("::::::::\r\n%s\r\n::::::::\r\n", name);
  2152. X
  2153. X          if ( strlen(pager) != 0 )
  2154. X            ofp = popen(pager, WMODE);
  2155. X          else
  2156. X            ofp = stdout;
  2157. X
  2158. X      save_quiet = quiet;
  2159. X          quiet = TRUE;
  2160. X          crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  2161. X          quiet = save_quiet;
  2162. X
  2163. X          if ( strlen(pager) != 0 )
  2164. X            pclose(ofp);
  2165. X    }
  2166. X      else if (output_to_test)
  2167. X        {
  2168. X          ofp = fopen(NULLFILE, WMODE);
  2169. X          crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  2170. X          fclose(ofp);
  2171. X        }
  2172. X      else
  2173. X        {
  2174. X#ifdef MSDOS
  2175. X          dosname(name);
  2176. X#endif
  2177. X      if ((ofp = open_with_make_path (name)) == NULL)
  2178. X        return;
  2179. X      else
  2180. X        {
  2181. X          crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  2182. X          fclose (ofp);
  2183. X        }
  2184. X    }
  2185. X
  2186. X      if (hdr->has_crc && (crc != hdr->crc))
  2187. X        if (output_to_test)
  2188. X          message ("Error:", "CRC failed\a");
  2189. X        else
  2190. X          error ("CRC failed\a");
  2191. X    }
  2192. X  else
  2193. X    {
  2194. X      /* NAME has trailing SLASH '/', (^_^) */
  2195. X      if (!output_to_stdout &&
  2196. X      !make_parent_path (name))
  2197. X    error (name);
  2198. X    }
  2199. X
  2200. X  if (!output_to_stdout && !output_to_test)
  2201. X    {
  2202. X      utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
  2203. X      utime (name, utimebuf);
  2204. X
  2205. X#ifdef NOT_COMPATIBLE_MODE
  2206. X      setfilemode(name, hdr->attribute);
  2207. X#else
  2208. X      chmod (name, hdr->unix_mode);
  2209. X#endif
  2210. X
  2211. X#ifndef MSDOS
  2212. X      chown (name, hdr->unix_uid, hdr->unix_gid);
  2213. X#endif
  2214. X      errno = 0;
  2215. X    }
  2216. X}
  2217. X
  2218. X
  2219. X/*
  2220. X  extract
  2221. X */
  2222. Xcmd_extract ()
  2223. X{
  2224. X  LzHeader    hdr;
  2225. X  long        pos;
  2226. X  FILE        *fp;
  2227. X
  2228. X  if ((fp = fopen (archive_name, RMODE)) == NULL)
  2229. X    if (!expand_archive_name (expanded_archive_name, archive_name))
  2230. X      error (archive_name);
  2231. X    else
  2232. X      {
  2233. X    errno = 0;
  2234. X        fp = xfopen (expanded_archive_name, RMODE);
  2235. X    archive_name = expanded_archive_name;
  2236. X      }
  2237. X
  2238. X  if (archive_is_msdos_sfx1 (archive_name))
  2239. X    {
  2240. X      skip_msdos_sfx1_code (fp);
  2241. X    }
  2242. X
  2243. X  while (get_header (fp, &hdr))
  2244. X    {
  2245. X      if (need_file (hdr.name))
  2246. X    {
  2247. X      pos = ftell (fp);
  2248. X      extract_one (fp, &hdr);
  2249. X      fseek (fp, pos + hdr.packed_size, SEEK_SET);
  2250. X    } else {
  2251. X      fseek (fp, hdr.packed_size, SEEK_CUR);
  2252. X    }
  2253. X    }
  2254. X
  2255. X  fclose (fp);
  2256. X
  2257. X  return;
  2258. X}
  2259. X
  2260. X/*----------------------------------------------------------------------*/
  2261. X/*                                    */
  2262. X/*----------------------------------------------------------------------*/
  2263. X
  2264. Xextern int encode_lzhuf ();
  2265. Xextern int encode_storerd_crc ();
  2266. X
  2267. Xappend_one (fp, nafp, hdr)
  2268. X     FILE *fp, *nafp;
  2269. X     LzHeader *hdr;
  2270. X{
  2271. X  long    header_pos, next_pos, org_pos, data_pos;
  2272. X  long    v_original_size, v_packed_size;
  2273. X
  2274. X  reading_filename = hdr->name;
  2275. X  writting_filename = temporary_name;
  2276. X
  2277. X  org_pos = ftell (fp);
  2278. X  header_pos = ftell (nafp);
  2279. X  write_header (nafp, hdr);    /* DUMMY */
  2280. X
  2281. X  if (hdr->original_size == 0)
  2282. X    return;            /* previous write_header is not DUMMY. (^_^) */
  2283. X
  2284. X  data_pos = ftell (nafp);
  2285. X  hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
  2286. X               &v_original_size, &v_packed_size, hdr->name);
  2287. X  if (v_packed_size < v_original_size)
  2288. X    {
  2289. X      next_pos = ftell (nafp);
  2290. X    }
  2291. X  else
  2292. X    {                /* retry by stored method */
  2293. X      fseek (fp, org_pos, SEEK_SET);
  2294. X      fseek (nafp, data_pos, SEEK_SET);
  2295. X      hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size,
  2296. X                    &v_original_size, &v_packed_size);
  2297. X      fflush (nafp);
  2298. X      next_pos = ftell (nafp);
  2299. X      ftruncate (fileno (nafp), next_pos);
  2300. X      bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  2301. X    }
  2302. X  hdr->original_size = v_original_size;
  2303. X  hdr->packed_size = v_packed_size;
  2304. X  fseek (nafp, header_pos, SEEK_SET);
  2305. X  write_header (nafp, hdr);
  2306. X  fseek (nafp, next_pos, SEEK_SET);
  2307. X}
  2308. X
  2309. Xwrite_tail (nafp)
  2310. X     FILE *nafp;
  2311. X{
  2312. X  putc (0x00, nafp);
  2313. X}
  2314. X
  2315. Xcopy_old_one (oafp, nafp, hdr)
  2316. X     FILE *oafp, *nafp;
  2317. X     LzHeader *hdr;
  2318. X{
  2319. X  if (noexec)
  2320. X    {
  2321. X      fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
  2322. X    }
  2323. X  else
  2324. X    {
  2325. X      reading_filename = archive_name;
  2326. X      writting_filename = temporary_name;
  2327. X      copy_file (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size);
  2328. X    }
  2329. X}
  2330. X
  2331. X
  2332. XFILE *append_it (name, oafp, nafp)
  2333. X     char *name;
  2334. X     FILE *oafp, *nafp;
  2335. X{
  2336. X  LzHeader    ahdr, hdr;
  2337. X  FILE        *fp;
  2338. X  long        old_header;
  2339. X  int        cmp;
  2340. X  int        filec;
  2341. X  char        **filev;
  2342. X  int        i;
  2343. X
  2344. X  struct stat    v_stat;
  2345. X  boolean    directory;
  2346. X
  2347. X  if (!delete_from_archive)
  2348. X    if (stat (name, &v_stat) < 0)
  2349. X      {
  2350. X        message ("Error:", name);
  2351. X        return oafp;
  2352. X      }
  2353. X
  2354. X  directory = ((v_stat.st_mode & S_IFMT) == S_IFDIR);
  2355. X
  2356. X  init_header (name, &v_stat, &hdr);
  2357. X
  2358. X  if (!delete_from_archive && !directory && !noexec)
  2359. X    fp = xfopen (name, RMODE);
  2360. X
  2361. X  while (oafp)
  2362. X    {
  2363. X      old_header = ftell (oafp);
  2364. X      if (!get_header (oafp, &ahdr))
  2365. X    {
  2366. X      fclose (oafp);
  2367. X      oafp = NULL;
  2368. X      break;
  2369. X    }
  2370. X      else
  2371. X    {
  2372. X      cmp = STRING_COMPARE (ahdr.name, hdr.name);
  2373. X      if (cmp < 0)
  2374. X        {        /* SKIP */
  2375. X          fseek (oafp, old_header, SEEK_SET);
  2376. X          copy_old_one (oafp, nafp, &ahdr);
  2377. X        }
  2378. X      else if (cmp == 0)
  2379. X        {        /* REPLACE */
  2380. X          fseek (oafp, ahdr.packed_size, SEEK_CUR);
  2381. X          break;
  2382. X        }
  2383. X      else        /* cmp > 0, INSERT */
  2384. X        {
  2385. X          fseek (oafp, old_header, SEEK_SET);
  2386. X          break;
  2387. X        }
  2388. X    }
  2389. X    }
  2390. X
  2391. X  if (delete_from_archive)
  2392. X    {
  2393. X      if (noexec)
  2394. X        fprintf (stderr, "DELETE %s\n", name);
  2395. X      else
  2396. X        printf ("%s - Deleted\n", name);
  2397. X    }
  2398. X  else
  2399. X    {
  2400. X      if ( !oafp || (cmp > 0) || !update_if_newer
  2401. X           || (ahdr.unix_last_modified_stamp < hdr.unix_last_modified_stamp) )
  2402. X    {
  2403. X      if (noexec)
  2404. X        fprintf (stderr, "APPEND %s\n", name);
  2405. X          else
  2406. X#ifdef STRICT
  2407. X            if ( !directory )
  2408. X#endif
  2409. X              if ( !update_freshen || (cmp == 0) )
  2410. X                append_one (fp, nafp, &hdr);
  2411. X    }
  2412. X      else
  2413. X    {                    /* archive has old one */
  2414. X      fseek (oafp, old_header, SEEK_SET);
  2415. X      copy_old_one (oafp, nafp, &ahdr);
  2416. X    }
  2417. X
  2418. X      if (!directory)
  2419. X    {
  2420. X      if (!noexec)
  2421. X        fclose (fp);
  2422. X    }
  2423. X      else
  2424. X    {            /* recurcive call */
  2425. X      if (find_files (name, &filec, &filev))
  2426. X        {
  2427. X          for (i = 0; i < filec; i ++)
  2428. X        oafp = append_it (filev[i], oafp, nafp);
  2429. X          free_files (filec, filev);
  2430. X        }
  2431. X      return oafp;
  2432. X    }
  2433. X    }
  2434. X
  2435. X  return oafp;
  2436. X}
  2437. X
  2438. X
  2439. Xremove_it (name)
  2440. X     char *name;
  2441. X{
  2442. X  struct stat    v_stat;
  2443. X  int        i;
  2444. X  char        **filev;
  2445. X  int        filec;
  2446. X
  2447. X  if (stat (name, &v_stat) < 0)
  2448. X    {
  2449. X      fprintf (stderr, "Cannot access \"%s\".\n", name);
  2450. X      return;
  2451. X    }
  2452. X
  2453. X  if ((v_stat.st_mode & S_IFMT) == S_IFDIR)
  2454. X    {
  2455. X      if (!find_files (name, &filec, &filev))
  2456. X    {
  2457. X          fprintf (stderr, "Cannot open directory \"%s\".\n", name);
  2458. X      return;
  2459. X    }
  2460. X
  2461. X      for (i = 0; i < filec; i ++)
  2462. X    remove_it (filev[i]);
  2463. X
  2464. X      free_files (filec, filev);
  2465. X
  2466. X      if (noexec)
  2467. X        printf ("REMOVE DIR %s\n", name);
  2468. X      else if (rmdir (name) < 0)
  2469. X        fprintf (stderr, "Cannot remove directory \"%s\".\n", name);
  2470. X      else if (!quiet)
  2471. X        printf ("%s - Removed\n", name);
  2472. X    }
  2473. X  else
  2474. X    {
  2475. X      if (noexec)
  2476. X        printf ("REMOVE %s\n", name);
  2477. X      else if (unlink (name) < 0)
  2478. X        fprintf (stderr, "Cannot delete \"%s\".\n", name);
  2479. X      else if (!quiet)
  2480. X        printf ("%s - Removed\n", name);
  2481. X    }
  2482. X}
  2483. X
  2484. X#ifdef FASTCOPY
  2485. X#define BUFFER_SIZE 16384
  2486. X
  2487. X#ifndef O_BINARY
  2488. X#define O_BINARY 0
  2489. X#endif
  2490. X
  2491. Xcopy_archive(src,dst )
  2492. Xchar *src;
  2493. Xchar *dst;
  2494. X{
  2495. X  int ih, oh;
  2496. X  unsigned chunk;
  2497. X  char *buffer = (char *) rson;
  2498. X
  2499. X  printf ("Copying temp to archive ... ");
  2500. X
  2501. X  ih = open (src, O_RDONLY | O_BINARY);
  2502. X  if ( ih == -1 )
  2503. X    error(src);
  2504. X  oh = open (dst, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
  2505. X  if ( oh == -1 )
  2506. X    error(dst);
  2507. X
  2508. X  while ( (chunk = read(ih, buffer, BUFFER_SIZE)) > 0 )
  2509. X    if ( write(oh, buffer, chunk) != chunk )
  2510. X      error(dst);
  2511. X
  2512. X  close (ih);
  2513. X  close (oh);
  2514. X
  2515. X  printf("\b\b\b\b   \b\b\b\b.\n");
  2516. X}
  2517. X#endif
  2518. X
  2519. Xcmd_append ()
  2520. X{
  2521. X  LzHeader    ahdr;
  2522. X  FILE        *oafp, *nafp;
  2523. X  char        backup_archive_name [ FILENAME_LENGTH ];
  2524. X  char        new_archive_name_buffer [ FILENAME_LENGTH ];
  2525. X  char        *new_archive_name;
  2526. X  int        i;
  2527. X  long        old_header;
  2528. X  struct stat    v_stat;
  2529. X  boolean    old_archive_exist;
  2530. X  extern    rename();
  2531. X
  2532. X  if (cmd_filec == 0)
  2533. X    return;
  2534. X
  2535. X  make_tmp_name (archive_name, temporary_name);
  2536. X
  2537. X  if ((oafp = fopen (archive_name, RMODE)) == NULL)
  2538. X    if (expand_archive_name (expanded_archive_name, archive_name))
  2539. X      {
  2540. X    errno = 0;
  2541. X        oafp = fopen (expanded_archive_name, RMODE);
  2542. X    archive_name = expanded_archive_name;
  2543. X      }
  2544. X
  2545. X  old_archive_exist = (oafp) ? TRUE : FALSE;
  2546. X  if (new_archive && oafp)
  2547. X    {
  2548. X      fclose (oafp);
  2549. X      oafp = NULL;
  2550. X    }
  2551. X
  2552. X  if (oafp && archive_is_msdos_sfx1 (archive_name))
  2553. X    {
  2554. X      skip_msdos_sfx1_code (oafp);
  2555. X      make_standard_archive_name (new_archive_name_buffer, archive_name);
  2556. X      new_archive_name = new_archive_name_buffer;
  2557. X    }
  2558. X  else
  2559. X    {
  2560. X      new_archive_name = archive_name;
  2561. X    }
  2562. X
  2563. X  errno = 0;
  2564. X  if (!noexec)
  2565. X    {
  2566. X      nafp = xfopen (temporary_name, WMODE);
  2567. X      remove_temporary_at_error = TRUE;
  2568. X    }
  2569. X
  2570. X  for (i = 0; i < cmd_filec; i ++)
  2571. X    oafp = append_it (cmd_filev[i], oafp, nafp);
  2572. X
  2573. X  if (oafp)
  2574. X    {
  2575. X      old_header = ftell (oafp);
  2576. X      while (get_header (oafp, &ahdr))
  2577. X    {
  2578. X      fseek (oafp, old_header, SEEK_SET);
  2579. X      copy_old_one (oafp, nafp, &ahdr);
  2580. X      old_header = ftell (oafp);
  2581. X    }
  2582. X      fclose (oafp);
  2583. X    }
  2584. X
  2585. X  if (!noexec)
  2586. X    {
  2587. X      write_tail (nafp);
  2588. X      fclose (nafp);
  2589. X    }
  2590. X
  2591. X  make_backup_name (backup_archive_name, archive_name);
  2592. X
  2593. X  if (!noexec && old_archive_exist)
  2594. X  {
  2595. X#ifdef ORIGINAL
  2596. X    if (rename(archive_name, backup_archive_name) < 0)
  2597. X      error (archive_name);
  2598. X    unlink(backup_archive_name);
  2599. X#endif
  2600. X  }
  2601. X
  2602. X  if (!quiet && new_archive_name == new_archive_name_buffer)
  2603. X    {                /* warning at old archive is SFX */
  2604. X      printf ("New Archive File is \"%s\"\n", new_archive_name);
  2605. X    }
  2606. X
  2607. X#ifdef ORIGINAL
  2608. X  if (!noexec && rename(temporary_name, new_archive_name) < 0)
  2609. X#endif
  2610. X
  2611. X    {
  2612. X
  2613. X      if (stat (temporary_name, &v_stat) < 0)
  2614. X    error (temporary_name);
  2615. X#ifdef FASTCOPY
  2616. X      copy_archive(temporary_name, archive_name);
  2617. X#else
  2618. X      oafp = xfopen (temporary_name, RMODE);
  2619. X      nafp = xfopen (archive_name, WMODE);
  2620. X      reading_filename = temporary_name;
  2621. X      writting_filename = archive_name;
  2622. X      copy_file (oafp, nafp, (long)v_stat.st_size);
  2623. X      fclose (nafp);
  2624. X      fclose (oafp);
  2625. X#endif
  2626. X
  2627. X      unlink (temporary_name);
  2628. X    }
  2629. X  remove_temporary_at_error = FALSE;
  2630. X
  2631. X  if (delete_after_append)
  2632. X    {
  2633. X      if (!quiet && !noexec)
  2634. X    printf ("Erasing...\n");
  2635. X      for (i = 0; i < cmd_filec; i ++)
  2636. X    remove_it (cmd_filev[i]);
  2637. X    }
  2638. X
  2639. X  return;
  2640. X}
  2641. END_OF_lharc.c
  2642. if test 49791 -ne `wc -c <lharc.c`; then
  2643.     echo shar: \"lharc.c\" unpacked with wrong size!
  2644. fi
  2645. # end of overwriting check
  2646. fi
  2647. if test -f lhdir.h -a "${1}" != "-c" ; then 
  2648.   echo shar: Will not over-write existing file \"lhdir.h\"
  2649. else
  2650. echo shar: Extracting \"lhdir.h\" \(1254 characters\)
  2651. sed "s/^X//" >lhdir.h <<'END_OF_lhdir.h'
  2652. X/*
  2653. X * @(#) dir.h 1.4 87/11/06   Public Domain.
  2654. X *
  2655. X *  A public domain implementation of BSD directory routines for
  2656. X *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  2657. X *  August 1897
  2658. X *  Ported to OS/2 by Kai Uwe Rommel and added scandir prototype
  2659. X *  December 1989
  2660. X */
  2661. X
  2662. X#define    rewinddir(dirp)    seekdir(dirp, 0L)
  2663. X
  2664. X#define    MAXNAMLEN    12
  2665. X
  2666. Xstruct direct
  2667. X{
  2668. X    ino_t    d_ino;            /* a bit of a farce */
  2669. X    int    d_reclen;        /* more farce */
  2670. X    int    d_namlen;        /* length of d_name */
  2671. X        char    d_name[MAXNAMLEN + 1];  /* garentee null termination */
  2672. X};
  2673. X
  2674. Xstruct _dircontents
  2675. X{
  2676. X    char    *_d_entry;
  2677. X    struct _dircontents    *_d_next;
  2678. X};
  2679. X
  2680. Xtypedef struct _dirdesc
  2681. X{
  2682. X    int        dd_id;    /* uniquely identify each open directory */
  2683. X    long        dd_loc;    /* where we are in directory entry is this */
  2684. X    struct _dircontents    *dd_contents;    /* pointer to contents of dir */
  2685. X    struct _dircontents    *dd_cp;    /* pointer to current position */
  2686. X} DIR;
  2687. X
  2688. Xextern  DIR            *opendir(char *);
  2689. Xextern  struct direct  *readdir(DIR *);
  2690. Xextern  void            seekdir(DIR *, long);
  2691. Xextern  long            telldir(DIR *);
  2692. Xextern  void            closedir(DIR *);
  2693. X
  2694. Xextern  int             scandir(char *, struct direct ***,
  2695. X                                int (*)(struct direct *), int (*)());
  2696. END_OF_lhdir.h
  2697. if test 1254 -ne `wc -c <lhdir.h`; then
  2698.     echo shar: \"lhdir.h\" unpacked with wrong size!
  2699. fi
  2700. # end of overwriting check
  2701. fi
  2702. if test -f lhio.c -a "${1}" != "-c" ; then 
  2703.   echo shar: Will not over-write existing file \"lhio.c\"
  2704. else
  2705. echo shar: Extracting \"lhio.c\" \(6280 characters\)
  2706. sed "s/^X//" >lhio.c <<'END_OF_lhio.c'
  2707. X/*----------------------------------------------------------------------*/
  2708. X/*        File I/O module for LHarc UNIX                */
  2709. X/*                                    */
  2710. X/*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  2711. X/*                                    */
  2712. X/*  V0.00  Original                1989.06.25  Y.Tagawa    */
  2713. X/*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa    */
  2714. X/*  V0.03a Fix few bugs                1989.07.04  Y.Tagawa    */
  2715. X/*----------------------------------------------------------------------*/
  2716. X
  2717. X#include <stdio.h>
  2718. X#include "lhio.h"
  2719. X
  2720. X#ifndef BUFFER_SIZE
  2721. X#define BUFFER_SIZE    16384
  2722. X#endif
  2723. X
  2724. X
  2725. Xextern int    text_mode;            /* in lharc.c */
  2726. XFILE            *crc_infile, *crc_outfile;      /* in lzhuf.c */
  2727. X
  2728. Xextern int rson[];
  2729. X
  2730. X/* These functions are NO-RETURN */
  2731. Xextern read_error ();
  2732. Xextern write_error ();
  2733. X
  2734. X
  2735. Xint        crc_getc_cashe;
  2736. Xunsigned int    crc_value;
  2737. Xunsigned int    crc_table[0x100];
  2738. Xlong        crc_size;
  2739. X
  2740. X
  2741. Xcrcsub (ptr, length)
  2742. X     char        *ptr;
  2743. X     register int    length;
  2744. X{
  2745. X  register unsigned char    *p;
  2746. X  register unsigned int        ctmp;
  2747. X
  2748. X  if (length != 0)
  2749. X    {
  2750. X      ctmp = crc_value;
  2751. X      p = (unsigned char*)ptr;
  2752. X      for (; length; length --)
  2753. X    {
  2754. X      ctmp ^= (unsigned int)*p++;
  2755. X      ctmp = (ctmp >> 8) ^ crc_table [ ctmp & 0xff ];
  2756. X    }
  2757. X      crc_value = ctmp;
  2758. X    }
  2759. X}
  2760. X
  2761. X#ifndef __GNUC__
  2762. Xvoid putc_crc (c)
  2763. X     int c;
  2764. X{
  2765. X  CRC_CHAR (c);
  2766. X  if (!text_mode || (c != 0x0d && c != 0x1a))
  2767. X    {
  2768. X      putc (c, crc_outfile);
  2769. X    }
  2770. X}
  2771. X
  2772. Xint getc_crc ()
  2773. X{
  2774. X  int    c;
  2775. X
  2776. X  if (crc_getc_cashe != EOF)
  2777. X    {
  2778. X      c = crc_getc_cashe;
  2779. X      crc_getc_cashe = EOF;
  2780. X      CRC_CHAR (c);
  2781. X      crc_size++;
  2782. X    }
  2783. X  else if ((c = getc (crc_infile)) != EOF)
  2784. X    {
  2785. X      if (text_mode && c == 0x0a)
  2786. X    {
  2787. X      crc_getc_cashe = c;
  2788. X      c = 0x0d;
  2789. X    }
  2790. X      CRC_CHAR (c);
  2791. X      crc_size++;
  2792. X    }
  2793. X  return c;
  2794. X}
  2795. X#endif
  2796. X
  2797. X
  2798. X
  2799. Xinit_crc ()
  2800. X{
  2801. X  static int        inited = 0;
  2802. X  register unsigned int    *p = crc_table;
  2803. X  register int        i, j;
  2804. X  register unsigned int    x;
  2805. X
  2806. X  if (!inited) {
  2807. X    for (j = 0; j < 256; j ++) {
  2808. X      x = j;
  2809. X      for (i = 0; i < 8; i ++) {
  2810. X    if ((x & 1) != 0) {
  2811. X      x = (x >> 1) ^ 0xa001;
  2812. X    } else {
  2813. X      x = (x >> 1);
  2814. X    }
  2815. X      }
  2816. X      *p ++ = x;
  2817. X    }
  2818. X    inited = 1;
  2819. X  }
  2820. X  crc_value = 0;
  2821. X  crc_getc_cashe = EOF;
  2822. X  crc_size = 0;
  2823. X}
  2824. X
  2825. X/*----------------------------------------------------------------------*/
  2826. X/*                                    */
  2827. X/*----------------------------------------------------------------------*/
  2828. X
  2829. X/* if return value is -1, see errno */
  2830. Xcopy_binary_file (ifp, ofp, size, crc_flag)
  2831. X     FILE    *ifp, *ofp;
  2832. X     long    size;
  2833. X     int    crc_flag;    /* as boolean value */
  2834. X{
  2835. X  char *buffer = (char *) rson;
  2836. X  int read_size;
  2837. X  int n;
  2838. X
  2839. X  /* safty */
  2840. X  fflush (ofp);
  2841. X
  2842. X  while (size > 0)
  2843. X    {
  2844. X      read_size = ((size < (long)BUFFER_SIZE) ? (int)size : BUFFER_SIZE);
  2845. X
  2846. X      n = fread (buffer, sizeof (char), read_size, ifp);
  2847. X
  2848. X      if (n == 0)
  2849. X    read_error ();
  2850. X
  2851. X      if (fwrite (buffer, sizeof (char), n, ofp) < n)
  2852. X    write_error ();
  2853. X
  2854. X      if (crc_flag)
  2855. X    crcsub (buffer, n);
  2856. X
  2857. X      size -= (long)n;
  2858. X    }
  2859. X}
  2860. X
  2861. X/* read UNIX text file '0A' and write generic text file '0D0A' */
  2862. Xwrite_generic_text_file (ifp, ofp, size)
  2863. X     FILE    *ifp, *ofp;
  2864. X     long    size;
  2865. X{
  2866. X  char        buffer[BUFFER_SIZE];
  2867. X  int        read_size, write_count, n, m;
  2868. X  register char    *p, *p1, *e;
  2869. X
  2870. X  /* safty */
  2871. X  fflush (ofp);
  2872. X
  2873. X  write_count = 0;
  2874. X
  2875. X  while (size > 0)
  2876. X    {
  2877. X      read_size = ((size < BUFFER_SIZE) ? (int)size : BUFFER_SIZE);
  2878. X
  2879. X      n = fread (buffer, sizeof (char), read_size, ifp);
  2880. X
  2881. X      if (n == 0)
  2882. X    read_error ();
  2883. X
  2884. X      for (p1 = p = buffer, e = buffer + n; p < e; p++)
  2885. X    {
  2886. X      if (*p == '\n')
  2887. X        {
  2888. X          if ((m = p - p1) != 0)
  2889. X        {
  2890. X          if (fwrite (p1, sizeof (char), m, ofp) < m)
  2891. X            write_error ();
  2892. X          crcsub (p1, m);
  2893. X        }
  2894. X          putc (0x0d, ofp);
  2895. X          if (feof (ofp))
  2896. X        write_error ();
  2897. X          CRC_CHAR (0x0d);
  2898. X          p1 = p;
  2899. X          write_count ++;
  2900. X        }
  2901. X    }
  2902. X      if ((m = p - p1) != 0)
  2903. X    {
  2904. X      if (fwrite (p1, sizeof (char), m, ofp) < m)
  2905. X        write_error ();
  2906. X      crcsub (p1, m);
  2907. X    }
  2908. X
  2909. X      write_count += (long)n;
  2910. X      size -= (long)n;
  2911. X    }
  2912. X
  2913. X  crc_size = write_count;
  2914. X}
  2915. X
  2916. X/* read generic text file '0D0A' and write UNIX text file '0A' */
  2917. Xread_generic_text_file (ifp, ofp, size, crc_flag)
  2918. X     FILE    *ifp, *ofp;
  2919. X     long    size;
  2920. X     int    crc_flag;
  2921. X{
  2922. X  char        buffer[BUFFER_SIZE];
  2923. X  int        read_size, write_size, n, m;
  2924. X  register char *p, *p1, *e;
  2925. X
  2926. X  /* safty */
  2927. X  fflush (ofp);
  2928. X
  2929. X  while (size > 0)
  2930. X    {
  2931. X      read_size = ((size < BUFFER_SIZE) ? (int)size : BUFFER_SIZE);
  2932. X
  2933. X      n = fread (buffer, sizeof (char), read_size, ifp);
  2934. X
  2935. X      if (n == 0)
  2936. X    read_error ();
  2937. X
  2938. X      crcsub (buffer, n);
  2939. X
  2940. X      for (p1 = p = buffer, e = buffer + n; p < e; p ++)
  2941. X    {
  2942. X      if (*p == 0x0d)
  2943. X        {
  2944. X          if ((m = p - p1) != 0)
  2945. X        {
  2946. X          if (fwrite (p1, sizeof (char), m, ofp) < m)
  2947. X            write_error ();
  2948. X        }
  2949. X          p1 = p+1;
  2950. X        }
  2951. X    }
  2952. X      if ((m = p - p1) != 0)
  2953. X    {
  2954. X      if (fwrite (p1, sizeof (char), m, ofp) < m)
  2955. X        write_error ();
  2956. X    }
  2957. X
  2958. X      size -= (long)n;
  2959. X    }
  2960. X}
  2961. X
  2962. X
  2963. X/*----------------------------------------------------------------------*/
  2964. X/*                                    */
  2965. X/*----------------------------------------------------------------------*/
  2966. X
  2967. X
  2968. Xcopy_file (ifp, ofp, size)
  2969. X     FILE    *ifp, *ofp;
  2970. X     long    size;
  2971. X{
  2972. X  copy_binary_file (ifp, ofp, size, 0);
  2973. X}
  2974. X
  2975. X/*ARGSUSED*/
  2976. Xint decode_stored_crc (ifp, ofp, original_size, name)
  2977. X     FILE    *ifp, *ofp;
  2978. X     long    original_size;
  2979. X     char    *name;
  2980. X{
  2981. X  init_crc ();
  2982. X
  2983. X  if (text_mode)
  2984. X    {
  2985. X      read_generic_text_file (ifp, ofp, original_size, 1);
  2986. X      return crc_value;
  2987. X    }
  2988. X  else
  2989. X    {
  2990. X      copy_binary_file (ifp, ofp, original_size, 1);
  2991. X      return crc_value;
  2992. X    }
  2993. X}
  2994. X
  2995. X/*ARGSUSED*/
  2996. Xint decode_stored_nocrc (ifp, ofp, original_size, name)
  2997. X     FILE    *ifp, *ofp;
  2998. X     long    original_size;
  2999. X     char    *name;
  3000. X{
  3001. X  if (text_mode)
  3002. X    {
  3003. X      read_generic_text_file (ifp, ofp, original_size, 0);
  3004. X      return 0;            /* DUMMY */
  3005. X    }
  3006. X  else
  3007. X    {
  3008. X      copy_binary_file (ifp, ofp, original_size, 0);
  3009. X    }
  3010. X  return 0;            /* DUMMY */
  3011. X}
  3012. X
  3013. Xint encode_stored_crc (ifp, ofp, size, original_size_var, write_size_var)
  3014. X     FILE       *ifp, *ofp;
  3015. X     long       size;
  3016. X     long    *original_size_var;
  3017. X     long    *write_size_var;
  3018. X{
  3019. X  init_crc ();
  3020. X
  3021. X  if (text_mode)
  3022. X    {
  3023. X      write_generic_text_file (ifp, ofp, size);
  3024. X      *original_size_var = *write_size_var = crc_size;
  3025. X      return crc_value;
  3026. X    }
  3027. X  else
  3028. X    {
  3029. X      copy_binary_file (ifp, ofp, size, 1);
  3030. X      *original_size_var = size;
  3031. X      *write_size_var = size;
  3032. X      return crc_value;
  3033. X    }
  3034. X}
  3035. END_OF_lhio.c
  3036. if test 6280 -ne `wc -c <lhio.c`; then
  3037.     echo shar: \"lhio.c\" unpacked with wrong size!
  3038. fi
  3039. # end of overwriting check
  3040. fi
  3041. if test -f lhio.h -a "${1}" != "-c" ; then 
  3042.   echo shar: Will not over-write existing file \"lhio.h\"
  3043. else
  3044. echo shar: Extracting \"lhio.h\" \(1388 characters\)
  3045. sed "s/^X//" >lhio.h <<'END_OF_lhio.h'
  3046. X/*----------------------------------------------------------------------*/
  3047. X/*        File I/O module for LHarc UNIX                */
  3048. X/*                                    */
  3049. X/*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  3050. X/*                                    */
  3051. X/*  V0.00  Original                1989.06.25  Y.Tagawa    */
  3052. X/*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa    */
  3053. X/*----------------------------------------------------------------------*/
  3054. X
  3055. Xextern int        text_mode;
  3056. X
  3057. Xextern unsigned int    crc_table[0x100];
  3058. Xextern unsigned int    crc_value;
  3059. Xextern int        crc_getc_cashe;
  3060. Xextern FILE        *crc_infile, *crc_outfile;
  3061. Xextern long        crc_size;
  3062. X
  3063. X
  3064. X#define CRC_CHAR(c)                        \
  3065. X{ register unsigned int ctmp = crc_value ^ c;             \
  3066. X    crc_value = (ctmp >> 8) ^ crc_table [ ctmp & 0xff ]; }
  3067. X
  3068. X
  3069. X
  3070. X#if defined (__GNUC__)
  3071. X/*#define inlnie*/
  3072. X
  3073. X/* DECODING */
  3074. X/* '0D0A' -> '0A' conversion and strip '1A' when text_mode */
  3075. Xstatic inline putc_crc (int c)
  3076. X{
  3077. X  CRC_CHAR (c);
  3078. X  if (!text_mode || (c != 0x0d && c != 0x1a))
  3079. X    {
  3080. X      putc (c, crc_outfile);
  3081. X    }
  3082. X}
  3083. X
  3084. X/* ENCODING */
  3085. X/* '0A' -> '0D0A' conversion when text_mode */
  3086. Xstatic inline int getc_crc ()
  3087. X{
  3088. X  int    c;
  3089. X
  3090. X  if (crc_getc_cashe != EOF)
  3091. X    {
  3092. X      c = crc_getc_cashe;
  3093. X      crc_getc_cashe = EOF;
  3094. X      CRC_CHAR (c);
  3095. X      crc_size++;
  3096. X    }
  3097. X  else if ((c = getc (crc_infile)) != EOF)
  3098. X    {
  3099. X      if (text_mode && c == 0x0a)
  3100. X    {
  3101. X      crc_getc_cashe = c;
  3102. X      c = 0x0d;
  3103. X    }
  3104. X      CRC_CHAR (c);
  3105. X      crc_size++;
  3106. X    }
  3107. X  return c;
  3108. X}
  3109. X#endif
  3110. END_OF_lhio.h
  3111. if test 1388 -ne `wc -c <lhio.h`; then
  3112.     echo shar: \"lhio.h\" unpacked with wrong size!
  3113. fi
  3114. # end of overwriting check
  3115. fi
  3116. if test -f lzhuf.c -a "${1}" != "-c" ; then 
  3117.   echo shar: Will not over-write existing file \"lzhuf.c\"
  3118. else
  3119. echo shar: Extracting \"lzhuf.c\" \(22465 characters\)
  3120. sed "s/^X//" >lzhuf.c <<'END_OF_lzhuf.c'
  3121. X/*----------------------------------------------------------------------*/
  3122. X/*        lzhuf.c : Encoding/Decoding module for LHarc        */
  3123. X/*                                    */
  3124. X/*    LZSS Algorithm            Haruhiko.Okumura        */
  3125. X/*    Adaptic Huffman Encoding    1989.05.27  Haruyasu.Yoshizaki    */
  3126. X/*                                    */
  3127. X/*                                    */
  3128. X/*    Modified for UNIX LHarc V0.01    1989.05.28  Y.Tagawa        */
  3129. X/*    Modified for UNIX LHarc V0.02    1989.05.29  Y.Tagawa        */
  3130. X/*    Modified for UNIX LHarc V0.03    1989.07.02  Y.Tagawa        */
  3131. X/*----------------------------------------------------------------------*/
  3132. X
  3133. X/* Use ANSI sequences for using only one line per file but
  3134. X * indicator dots on next line */
  3135. X/* #define ANSI */
  3136. X
  3137. X#ifndef ANSI
  3138. X#define DOT       '.'
  3139. X#define BALL      'o'
  3140. X#else
  3141. X#define DOT       249
  3142. X#define BALL      3
  3143. X#define CURSORUP  "\033[A"
  3144. X#define ERASEEOL  "\033[K"
  3145. X#endif
  3146. X
  3147. X#include <stdio.h>
  3148. X
  3149. X#ifndef SELFMAIN
  3150. X#include "lhio.h"
  3151. X#else
  3152. X#define EXIT_SUCCESS    0
  3153. X#define EXIT_FAILURE    1
  3154. X#endif
  3155. X
  3156. X
  3157. X
  3158. XFILE *infile, *outfile;
  3159. Xlong textsize, codesize;
  3160. X
  3161. X
  3162. X#define INDICATOR_THRESHOLD    4096L
  3163. X#define MAX_INDICATOR_COUNT     78
  3164. Xlong indicator_count;
  3165. Xlong indicator_threshold;
  3166. X
  3167. X#ifdef SELFMAIN
  3168. Xint quiet = 0;
  3169. X#else
  3170. Xextern int quiet;
  3171. Xextern int output_to_test;
  3172. X#endif
  3173. X
  3174. X
  3175. X#ifdef SELFMAIN
  3176. X#define SETUP_PUTC_CRC(fp)    /* nothing */
  3177. X#define SETUP_GETC_CRC(fp)    /* nothing */
  3178. X#define PUTC_CRC(c)        putc((c),(outfile))
  3179. X#define GETC_CRC()        getc(infile)
  3180. X#define END_PUTC_CRC()
  3181. X#define END_GETC_CRC()
  3182. X#else
  3183. X#define SETUP_PUTC_CRC(fp)    crc_outfile = fp
  3184. X#define SETUP_GETC_CRC(fp)    crc_infile = fp
  3185. X#define PUTC_CRC(c)        putc_crc(c)
  3186. X#define GETC_CRC()        getc_crc()
  3187. X#define END_PUTC_CRC()
  3188. X#define END_GETC_CRC()
  3189. X#endif
  3190. X
  3191. X
  3192. X
  3193. X
  3194. X#ifdef SELFMAIN
  3195. Xvoid Error (message)
  3196. X    char *message;
  3197. X{
  3198. X    printf("\n%s\n", message);
  3199. X    exit(EXIT_FAILURE);
  3200. X}
  3201. X#endif
  3202. X
  3203. X/*----------------------------------------------------------------------*/
  3204. X/*                                    */
  3205. X/*        LZSS ENCODING                        */
  3206. X/*                                    */
  3207. X/*----------------------------------------------------------------------*/
  3208. X
  3209. X#define N        4096    /* buffer size */
  3210. X#define F        60    /* pre-sence buffer size */
  3211. X#define THRESHOLD    2
  3212. X#define NIL        N    /* term of tree */
  3213. X
  3214. Xunsigned char    text_buf[N + F - 1];
  3215. Xunsigned int     match_position, match_length;
  3216. Xint              lson[N + 1], rson[N + 1 + N], dad[N + 1];
  3217. Xunsigned char    same[N + 1];
  3218. X
  3219. X
  3220. X/* Initialize Tree */
  3221. XInitTree ()
  3222. X{
  3223. X    register int *p, *e;
  3224. X
  3225. X    for (p = rson + N + 1, e = rson + N + N; p <= e; )
  3226. X        *p++ = NIL;
  3227. X    for (p = dad, e = dad + N; p < e; )
  3228. X        *p++ = NIL;
  3229. X}
  3230. X
  3231. X
  3232. X/* Insert to node */
  3233. XInsertNode (r)
  3234. X    register int r;
  3235. X{
  3236. X    register int        p;
  3237. X    int            cmp;
  3238. X    register unsigned char    *key;
  3239. X    register unsigned int    c;
  3240. X    register unsigned int    i, j;
  3241. X
  3242. X    cmp = 1;
  3243. X    key = &text_buf[r];
  3244. X    i = key[1] ^ key[2];
  3245. X    i ^= i >> 4;
  3246. X    p = N + 1 + key[0] + ((i & 0x0f) << 8);
  3247. X    rson[r] = lson[r] = NIL;
  3248. X    match_length = 0;
  3249. X    i = j = 1;
  3250. X    for ( ; ; ) {
  3251. X        if (cmp >= 0) {
  3252. X            if (rson[p] != NIL) {
  3253. X                p = rson[p];
  3254. X                j = same[p];
  3255. X            } else {
  3256. X                rson[p] = r;
  3257. X                dad[r] = p;
  3258. X                same[r] = i;
  3259. X                return;
  3260. X            }
  3261. X        } else {
  3262. X            if (lson[p] != NIL) {
  3263. X                p = lson[p];
  3264. X                j = same[p];
  3265. X            } else {
  3266. X                lson[p] = r;
  3267. X                dad[r] = p;
  3268. X                same[r] = i;
  3269. X                return;
  3270. X            }
  3271. X        }
  3272. X
  3273. X        if (i > j) {
  3274. X            i = j;
  3275. X            cmp = key[i] - text_buf[p + i];
  3276. X        } else
  3277. X        if (i == j) {
  3278. X            for (; i < F; i++)
  3279. X                if ((cmp = key[i] - text_buf[p + i]) != 0)
  3280. X                    break;
  3281. X        }
  3282. X
  3283. X        if (i > THRESHOLD) {
  3284. X            if (i > match_length) {
  3285. X                match_position = ((r - p) & (N - 1)) - 1;
  3286. X                if ((match_length = i) >= F)
  3287. X                    break;
  3288. X            } else
  3289. X            if (i == match_length) {
  3290. X                if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
  3291. X                    match_position = c;
  3292. X                }
  3293. X            }
  3294. X        }
  3295. X    }
  3296. X    same[r] = same[p];
  3297. X    dad[r] = dad[p];
  3298. X    lson[r] = lson[p];
  3299. X    rson[r] = rson[p];
  3300. X    dad[lson[p]] = r;
  3301. X    dad[rson[p]] = r;
  3302. X    if (rson[dad[p]] == p)
  3303. X        rson[dad[p]] = r;
  3304. X    else
  3305. X        lson[dad[p]] = r;
  3306. X    dad[p] = NIL;  /* remove p */
  3307. X}
  3308. X
  3309. X
  3310. Xlink (n, p, q)
  3311. X    int n, p, q;
  3312. X{
  3313. X    register unsigned char *s1, *s2, *s3;
  3314. X    if (p >= NIL) {
  3315. X        same[q] = 1;
  3316. X        return;
  3317. X    }
  3318. X    s1 = text_buf + p + n;
  3319. X    s2 = text_buf + q + n;
  3320. X    s3 = text_buf + p + F;
  3321. X    while (s1 < s3) {
  3322. X        if (*s1++ != *s2++) {
  3323. X            same[q] = s1 - 1 - text_buf - p;
  3324. X            return;
  3325. X        }
  3326. X    }
  3327. X    same[q] = F;
  3328. X}
  3329. X
  3330. X
  3331. Xlinknode (p, q, r)
  3332. X    int p, q, r;
  3333. X{
  3334. X    int cmp;
  3335. X
  3336. X    if ((cmp = same[q] - same[r]) == 0) {
  3337. X        link(same[q], p, r);
  3338. X    } else if (cmp < 0) {
  3339. X        same[r] = same[q];
  3340. X    }
  3341. X}
  3342. X
  3343. XDeleteNode (p)
  3344. X    register int p;
  3345. X{
  3346. X    register int  q;
  3347. X
  3348. X    if (dad[p] == NIL)
  3349. X        return;            /* has no linked */
  3350. X    if (rson[p] == NIL) {
  3351. X        if ((q = lson[p]) != NIL)
  3352. X            linknode(dad[p], p, q);
  3353. X    } else
  3354. X    if (lson[p] == NIL) {
  3355. X        q = rson[p];
  3356. X        linknode(dad[p], p, q);
  3357. X    } else {
  3358. X        q = lson[p];
  3359. X        if (rson[q] != NIL) {
  3360. X            do {
  3361. X                q = rson[q];
  3362. X            } while (rson[q] != NIL);
  3363. X            if (lson[q] != NIL)
  3364. X                linknode(dad[q], q, lson[q]);
  3365. X            link(1, q, lson[p]);
  3366. X            rson[dad[q]] = lson[q];
  3367. X            dad[lson[q]] = dad[q];
  3368. X            lson[q] = lson[p];
  3369. X            dad[lson[p]] = q;
  3370. X        }
  3371. X        link(1, dad[p], q);
  3372. X        link(1, q, rson[p]);
  3373. X        rson[q] = rson[p];
  3374. X        dad[rson[p]] = q;
  3375. X    }
  3376. X    dad[q] = dad[p];
  3377. X    if (rson[dad[p]] == p)
  3378. X        rson[dad[p]] = q;
  3379. X    else
  3380. X        lson[dad[p]] = q;
  3381. X    dad[p] = NIL;
  3382. X}
  3383. X
  3384. X/*----------------------------------------------------------------------*/
  3385. X/*                                    */
  3386. X/*        HUFFMAN ENCODING                    */
  3387. X/*                                    */
  3388. X/*----------------------------------------------------------------------*/
  3389. X
  3390. X#define N_CHAR      (256 - THRESHOLD + F) /* {code : 0 .. N_CHAR-1} */
  3391. X#define T         (N_CHAR * 2 - 1)    /* size of table */
  3392. X#define R         (T - 1)            /* root position */
  3393. X#define MAX_FREQ    0x8000    /* tree update timing from frequency */
  3394. X
  3395. Xtypedef unsigned char uchar;
  3396. X
  3397. X
  3398. X
  3399. X/* TABLE OF ENCODE/DECODE for upper 6bits position information */
  3400. X
  3401. X/* for encode */
  3402. Xuchar p_len[64] = {
  3403. X    0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
  3404. X    0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
  3405. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3406. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3407. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3408. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3409. X    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  3410. X    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
  3411. X};
  3412. X
  3413. Xuchar p_code[64] = {
  3414. X    0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
  3415. X    0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
  3416. X    0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
  3417. X    0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
  3418. X    0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
  3419. X    0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
  3420. X    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
  3421. X    0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
  3422. X};
  3423. X
  3424. X/* for decode */
  3425. Xuchar d_code[256] = {
  3426. X    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  3427. X    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  3428. X    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  3429. X    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  3430. X    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  3431. X    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  3432. X    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  3433. X    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  3434. X    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  3435. X    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  3436. X    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  3437. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3438. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3439. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3440. X    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  3441. X    0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
  3442. X    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
  3443. X    0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
  3444. X    0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
  3445. X    0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
  3446. X    0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
  3447. X    0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
  3448. X    0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
  3449. X    0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
  3450. X    0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
  3451. X    0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
  3452. X    0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
  3453. X    0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
  3454. X    0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
  3455. X    0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
  3456. X    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  3457. X    0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  3458. X};
  3459. X
  3460. Xuchar d_len[256] = {
  3461. X    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  3462. X    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  3463. X    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  3464. X    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  3465. X    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  3466. X    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  3467. X    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  3468. X    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  3469. X    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  3470. X    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  3471. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3472. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3473. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3474. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3475. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3476. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3477. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3478. X    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  3479. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3480. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3481. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3482. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3483. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3484. X    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  3485. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3486. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3487. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3488. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3489. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3490. X    0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  3491. X    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  3492. X    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  3493. X};
  3494. X
  3495. Xunsigned freq[T + 1];    /* frequency table */
  3496. X
  3497. Xint prnt[T + N_CHAR];    /* points to parent node */
  3498. X/* notes :
  3499. X   prnt[T .. T + N_CHAR - 1] used by
  3500. X   indicates leaf position that corresponding to code */
  3501. X
  3502. Xint son[T];              /* points to son node (son[i],son[i+]) */
  3503. X
  3504. Xunsigned getbuf = 0;
  3505. Xuchar getlen = 0;
  3506. X
  3507. X
  3508. X/* get one bit */
  3509. X/* returning in Bit 0 */
  3510. Xint GetBit ()
  3511. X{
  3512. X    register unsigned int dx = getbuf;
  3513. X    register unsigned int c;
  3514. X
  3515. X    if (getlen <= 8)
  3516. X        {
  3517. X            c = getc (infile);
  3518. X            if ((int)c < 0) c = 0;
  3519. X            dx |= c << (8 - getlen);
  3520. X            getlen += 8;
  3521. X        }
  3522. X    getbuf = dx << 1;
  3523. X    getlen--;
  3524. X    return (dx & 0x8000) ? 1 : 0;
  3525. X}
  3526. X
  3527. X/* get one byte */
  3528. X/* returning in Bit7...0 */
  3529. Xint GetByte ()
  3530. X{
  3531. X    register unsigned int dx = getbuf;
  3532. X    register unsigned c;
  3533. X
  3534. X    if (getlen <= 8) {
  3535. X        c = getc (infile);
  3536. X        if ((int)c < 0) c = 0;
  3537. X        dx |= c << (8 - getlen);
  3538. X        getlen += 8;
  3539. X    }
  3540. X    getbuf = dx << 8;
  3541. X    getlen -= 8;
  3542. X    return (dx >> 8) & 0xff;
  3543. X}
  3544. X
  3545. X/* get N bit */
  3546. X/* returning in Bit(N-1)...Bit 0 */
  3547. Xint GetNBits (n)
  3548. X    register unsigned int n;
  3549. X{
  3550. X    register unsigned int dx = getbuf;
  3551. X    register unsigned int c;
  3552. X    static int mask[17] = {
  3553. X        0x0000,
  3554. X        0x0001, 0x0003, 0x0007, 0x000f,
  3555. X        0x001f, 0x003f, 0x007f, 0x00ff,
  3556. X        0x01ff, 0x03ff, 0x07ff, 0x0fff,
  3557. X        0x1fff, 0x3fff, 0x0fff, 0xffff };
  3558. X    static int shift[17] = {
  3559. X        16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
  3560. X
  3561. X    if (getlen <= 8)
  3562. X        {
  3563. X            c = getc (infile);
  3564. X            if ((int)c < 0) c = 0;
  3565. X            dx |= c << (8 - getlen);
  3566. X            getlen += 8;
  3567. X        }
  3568. X    getbuf = dx << n;
  3569. X    getlen -= n;
  3570. X    return (dx >> shift[n]) & mask[n];
  3571. X}
  3572. X
  3573. Xunsigned putbuf = 0;
  3574. Xuchar putlen = 0;
  3575. X
  3576. X/* output C bits */
  3577. XPutcode (l, c)
  3578. X    register int l;
  3579. X    register unsigned int c;
  3580. X{
  3581. X    register len = putlen;
  3582. X    register unsigned int b = putbuf;
  3583. X    b |= c >> len;
  3584. X    if ((len += l) >= 8) {
  3585. X        putc (b >> 8, outfile);
  3586. X        if ((len -= 8) >= 8) {
  3587. X            putc (b, outfile);
  3588. X            codesize += 2;
  3589. X            len -= 8;
  3590. X            b = c << (l - len);
  3591. X        } else {
  3592. X            b <<= 8;
  3593. X            codesize++;
  3594. X        }
  3595. X    }
  3596. X    putbuf = b;
  3597. X    putlen = len;
  3598. X}
  3599. X
  3600. X
  3601. X/* Initialize tree */
  3602. X
  3603. XStartHuff ()
  3604. X{
  3605. X    register int i, j;
  3606. X
  3607. X    for (i = 0; i < N_CHAR; i++) {
  3608. X        freq[i] = 1;
  3609. X        son[i] = i + T;
  3610. X        prnt[i + T] = i;
  3611. X    }
  3612. X    i = 0; j = N_CHAR;
  3613. X    while (j <= R) {
  3614. X        freq[j] = freq[i] + freq[i + 1];
  3615. X        son[j] = i;
  3616. X        prnt[i] = prnt[i + 1] = j;
  3617. X        i += 2; j++;
  3618. X    }
  3619. X    freq[T] = 0xffff;
  3620. X    prnt[R] = 0;
  3621. X    putlen = getlen = 0;
  3622. X    putbuf = getbuf = 0;
  3623. X}
  3624. X
  3625. X
  3626. X/* reconstruct tree */
  3627. Xreconst ()
  3628. X{
  3629. X    register int i, j, k;
  3630. X    register unsigned f;
  3631. X
  3632. X    /* correct leaf node into of first half,
  3633. X       and set these freqency to (freq+1)/2       */
  3634. X    j = 0;
  3635. X    for (i = 0; i < T; i++) {
  3636. X        if (son[i] >= T) {
  3637. X            freq[j] = (freq[i] + 1) / 2;
  3638. X            son[j] = son[i];
  3639. X            j++;
  3640. X        }
  3641. X    }
  3642. X    /* build tree.  Link sons first */
  3643. X    for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
  3644. X        k = i + 1;
  3645. X        f = freq[j] = freq[i] + freq[k];
  3646. X        for (k = j - 1; f < freq[k]; k--);
  3647. X        k++;
  3648. X        {    register unsigned *p, *e;
  3649. X            for (p = &freq[j], e = &freq[k]; p > e; p--)
  3650. X                p[0] = p[-1];
  3651. X            freq[k] = f;
  3652. X        }
  3653. X        {    register int *p, *e;
  3654. X            for (p = &son[j], e = &son[k]; p > e; p--)
  3655. X                p[0] = p[-1];
  3656. X            son[k] = i;
  3657. X        }
  3658. X    }
  3659. X    /* link parents */
  3660. X    for (i = 0; i < T; i++) {
  3661. X        if ((k = son[i]) >= T) {
  3662. X            prnt[k] = i;
  3663. X        } else {
  3664. X            prnt[k] = prnt[k + 1] = i;
  3665. X        }
  3666. X    }
  3667. X}
  3668. X
  3669. X
  3670. X/* update given code's frequency, and update tree */
  3671. X
  3672. Xupdate (c)
  3673. X    unsigned int    c;
  3674. X{
  3675. X    register unsigned *p;
  3676. X    register int i, j, k, l;
  3677. X
  3678. X    if (freq[R] == MAX_FREQ) {
  3679. X        reconst();
  3680. X    }
  3681. X    c = prnt[c + T];
  3682. X    do {
  3683. X        k = ++freq[c];
  3684. X
  3685. X        /* swap nodes when become wrong frequency order. */
  3686. X        if (k > freq[l = c + 1]) {
  3687. X            for (p = freq+l+1; k > *p++; ) ;
  3688. X            l = p - freq - 2;
  3689. X            freq[c] = p[-2];
  3690. X            p[-2] = k;
  3691. X
  3692. X            i = son[c];
  3693. X            prnt[i] = l;
  3694. X            if (i < T) prnt[i + 1] = l;
  3695. X
  3696. X            j = son[l];
  3697. X            son[l] = i;
  3698. X
  3699. X            prnt[j] = c;
  3700. X            if (j < T) prnt[j + 1] = c;
  3701. X            son[c] = j;
  3702. X
  3703. X            c = l;
  3704. X        }
  3705. X    } while ((c = prnt[c]) != 0);    /* loop until reach to root */
  3706. X}
  3707. X
  3708. X/* unsigned code, len; */
  3709. X
  3710. XEncodeChar (c)
  3711. X    unsigned c;
  3712. X{
  3713. X    register int *p;
  3714. X    register unsigned long i;
  3715. X    register int j, k;
  3716. X
  3717. X    i = 0;
  3718. X    j = 0;
  3719. X    p = prnt;
  3720. X    k = p[c + T];
  3721. X
  3722. X    /* trace links from leaf node to root */
  3723. X    do {
  3724. X        i >>= 1;
  3725. X
  3726. X        /* if node index is odd, trace larger of sons */
  3727. X        if (k & 1) i += 0x80000000;
  3728. X
  3729. X        j++;
  3730. X    } while ((k = p[k]) != R) ;
  3731. X    if (j > 16) {
  3732. X        Putcode(16, (unsigned int)(i >> 16));
  3733. X        Putcode(j - 16, (unsigned int)i);
  3734. X    } else {
  3735. X        Putcode(j, (unsigned int)(i >> 16));
  3736. X    }
  3737. X/*    code = i; */
  3738. X/*     len = j; */
  3739. X    update(c);
  3740. X}
  3741. X
  3742. XEncodePosition (c)
  3743. X    unsigned c;
  3744. X{
  3745. X    unsigned i;
  3746. X
  3747. X    /* output upper 6bit from table */
  3748. X    i = c >> 6;
  3749. X    Putcode((int)(p_len[i]), (unsigned int)(p_code[i]) << 8);
  3750. X
  3751. X    /* output lower 6 bit */
  3752. X    Putcode(6, (unsigned int)(c & 0x3f) << 10);
  3753. X}
  3754. X
  3755. XEncodeEnd ()
  3756. X{
  3757. X    if (putlen) {
  3758. X        putc(putbuf >> 8, outfile);
  3759. X        codesize++;
  3760. X    }
  3761. X}
  3762. X
  3763. Xint DecodeChar ()
  3764. X{
  3765. X    register unsigned c;
  3766. X
  3767. X    c = son[R];
  3768. X
  3769. X    /* trace from root to leaf,
  3770. X       got bit is 0 to small(son[]), 1 to large (son[]+1) son node */
  3771. X    while (c < T) {
  3772. X        c += GetBit();
  3773. X        c = son[c];
  3774. X    }
  3775. X    c -= T;
  3776. X    update(c);
  3777. X    return c;
  3778. X}
  3779. X
  3780. Xint DecodePosition ()
  3781. X{
  3782. X    unsigned i, j, c;
  3783. X
  3784. X    /* decode upper 6bit from table */
  3785. X    i = GetByte();
  3786. X    c = (unsigned)d_code[i] << 6;
  3787. X    j = d_len[i];
  3788. X
  3789. X    /* get lower 6bit */
  3790. X    j -= 2;
  3791. X    return c | (((i << j) | GetNBits (j)) & 0x3f);
  3792. X}
  3793. X
  3794. X
  3795. XEncode ()
  3796. X{
  3797. X    register int  i, c, len, r, s, last_match_length;
  3798. X
  3799. X    if (textsize == 0)
  3800. X        return;
  3801. X
  3802. X    textsize = 0;
  3803. X    StartHuff();
  3804. X    InitTree();
  3805. X    s = 0;
  3806. X    r = N - F;
  3807. X    for (i = s; i < r; i++)
  3808. X        text_buf[i] = ' ';
  3809. X    for (len = 0; len < F && (c = GETC_CRC()) != EOF; len++)
  3810. X        text_buf[r + len] = c;
  3811. X    textsize = len;
  3812. X    for (i = 1; i <= F; i++)
  3813. X        InsertNode(r - i);
  3814. X    InsertNode(r);
  3815. X    do {
  3816. X        if (match_length > len)
  3817. X            match_length = len;
  3818. X        if (match_length <= THRESHOLD) {
  3819. X            match_length = 1;
  3820. X            EncodeChar(text_buf[r]);
  3821. X        } else {
  3822. X            EncodeChar(255 - THRESHOLD + match_length);
  3823. X            EncodePosition(match_position);
  3824. X        }
  3825. X        last_match_length = match_length;
  3826. X        for (i = 0; i < last_match_length &&
  3827. X                (c = GETC_CRC()) != EOF; i++) {
  3828. X            DeleteNode(s);
  3829. X            text_buf[s] = c;
  3830. X            if (s < F - 1)
  3831. X                text_buf[s + N] = c;
  3832. X            s = (s + 1) & (N - 1);
  3833. X            r = (r + 1) & (N - 1);
  3834. X            InsertNode(r);
  3835. X        }
  3836. X
  3837. X        textsize += i;
  3838. X        if ((textsize > indicator_count) && !quiet) {
  3839. X            putchar (BALL);
  3840. X            fflush (stdout);
  3841. X            indicator_count += indicator_threshold;
  3842. X        }
  3843. X        while (i++ < last_match_length) {
  3844. X            DeleteNode(s);
  3845. X            s = (s + 1) & (N - 1);
  3846. X            r = (r + 1) & (N - 1);
  3847. X            if (--len) InsertNode(r);
  3848. X        }
  3849. X    } while (len > 0);
  3850. X    EncodeEnd();
  3851. X    END_GETC_CRC ();
  3852. X}
  3853. X
  3854. XDecode ()
  3855. X{
  3856. X    register int    i, j, k, r, c;
  3857. X    register long    count;
  3858. X
  3859. X#ifdef SELFMAIN
  3860. X    if (textsize == 0)
  3861. X        return;
  3862. X#endif
  3863. X    StartHuff();
  3864. X    for (i = 0; i < N - F; i++)
  3865. X        text_buf[i] = ' ';
  3866. X    r = N - F;
  3867. X    for (count = 0; count < textsize; ) {
  3868. X        c = DecodeChar();
  3869. X        if (c < 256) {
  3870. X            PUTC_CRC (c);
  3871. X            text_buf[r++] = c;
  3872. X            r &= (N - 1);
  3873. X            count++;
  3874. X        } else {
  3875. X            i = (r - DecodePosition() - 1) & (N - 1);
  3876. X            j = c - 255 + THRESHOLD;
  3877. X            for (k = 0; k < j; k++) {
  3878. X                c = text_buf[(i + k) & (N - 1)];
  3879. X                PUTC_CRC (c);
  3880. X                text_buf[r++] = c;
  3881. X                r &= (N - 1);
  3882. X                count++;
  3883. X            }
  3884. X        }
  3885. X
  3886. X        if (!quiet && (count > indicator_count)) {
  3887. X            putchar (BALL);
  3888. X            fflush (stdout);
  3889. X            indicator_count += indicator_threshold;
  3890. X        }
  3891. X    }
  3892. X    END_PUTC_CRC ();
  3893. X}
  3894. X
  3895. X
  3896. X/*----------------------------------------------------------------------*/
  3897. X/*                                    */
  3898. X/*        LARC                            */
  3899. X/*                                    */
  3900. X/*----------------------------------------------------------------------*/
  3901. X
  3902. X#define F_OLD    18    /* look ahead buffer size for LArc */
  3903. X
  3904. X/* intialize buffer for LArc type 5 */
  3905. XInitBuf ()
  3906. X{
  3907. X    register unsigned char *p = text_buf;
  3908. X    register int i, j;
  3909. X    for (i = 0; i < 256; i ++)
  3910. X        for (j = 0; j < 13; j ++)
  3911. X            *p ++ = i;
  3912. X    for (i = 0; i < 256; i ++)
  3913. X        *p ++ = i;
  3914. X    for (i = 0; i < 256; i ++)
  3915. X        *p ++ = 255 - i;
  3916. X    for (i = 0; i < 128; i ++)
  3917. X        *p ++ = 0;
  3918. X    for (i = 0; i < 128; i ++)
  3919. X        *p ++ = 0x20;
  3920. X}
  3921. X
  3922. X/* Decode LArc type 5 */
  3923. XDecodeOld ()
  3924. X{
  3925. X    register int si, di;
  3926. X    register long count;
  3927. X    int    dl, dh, al, cx;
  3928. X    if (textsize == 0)
  3929. X        return;
  3930. X
  3931. X    InitBuf ();
  3932. X    di = N - F_OLD;
  3933. X    dl = 0x80;
  3934. X
  3935. X    for (count = 0; count < textsize; ) {
  3936. X        dl = ((dl << 1) | (dl >> 7)) & 0xff;
  3937. X        if (dl & 0x01)
  3938. X            dh = getc (infile);
  3939. X        al = getc (infile);
  3940. X        if ((dh & dl) != 0) {
  3941. X            PUTC_CRC (al);
  3942. X            text_buf[di] = al;
  3943. X            di = (di + 1) & (N - 1);
  3944. X            count ++;
  3945. X        } else {
  3946. X            cx = getc (infile);
  3947. X            si = (al & 0x00ff) | ((cx << 4) & 0x0f00);
  3948. X            cx = (cx & 0x000f) + 3;
  3949. X            count += cx;
  3950. X            do {
  3951. X                text_buf[di] = al = text_buf[si];
  3952. X                PUTC_CRC (al);
  3953. X                si = (si + 1) & (N - 1);
  3954. X                di = (di + 1) & (N - 1);
  3955. X            } while (--cx != 0) ;
  3956. X        }
  3957. X
  3958. X        if (!quiet && (count > indicator_count)) {
  3959. X            putchar (BALL);
  3960. X            fflush (stdout);
  3961. X            indicator_count += indicator_threshold;
  3962. X        }
  3963. X    }
  3964. X    END_PUTC_CRC ();
  3965. X}
  3966. X
  3967. X
  3968. X
  3969. X/*----------------------------------------------------------------------*/
  3970. X/*                                    */
  3971. X/*        Global Entries for Archiver Driver            */
  3972. X/*                                    */
  3973. X/*----------------------------------------------------------------------*/
  3974. X
  3975. X
  3976. Xstart_indicator (name, size, msg)
  3977. X    char *name;
  3978. X    long size;
  3979. X    char *msg;
  3980. X{
  3981. X    long    i;
  3982. X    int    m;
  3983. X
  3984. X    if (quiet)
  3985. X        return;
  3986. X
  3987. X#ifdef ANSI
  3988. X    m = MAX_INDICATOR_COUNT;
  3989. X#else
  3990. X    m = MAX_INDICATOR_COUNT - strlen (name);
  3991. X#endif
  3992. X    if (m < 0)
  3993. X        m = 3;        /* (^_^) */
  3994. X
  3995. X#ifdef ANSI
  3996. X        printf ("\r%s - %s:\n", name, msg);
  3997. X#else
  3998. X        printf ("\r%s - %s :  ", name, msg);
  3999. X#endif
  4000. X
  4001. X    indicator_threshold =
  4002. X        ((size  + (m * INDICATOR_THRESHOLD - 1)) /
  4003. X         (m * INDICATOR_THRESHOLD) *
  4004. X         INDICATOR_THRESHOLD);
  4005. X    i = ((size + (indicator_threshold - 1)) / indicator_threshold);
  4006. X    while (i--)
  4007. X        putchar (DOT);
  4008. X    indicator_count = 0;
  4009. X#ifdef ANSI
  4010. X        printf ("\r%s%s - %s:\n", CURSORUP, name, msg);
  4011. X#else
  4012. X        printf ("\r%s - %s :  ", name, msg);
  4013. X#endif
  4014. X    fflush (stdout);
  4015. X}
  4016. X
  4017. Xfinish_indicator2 (name, msg, pcnt)
  4018. X    char *name;
  4019. X    char *msg;
  4020. X    int pcnt;
  4021. X{
  4022. X    if (quiet)
  4023. X        return;
  4024. X
  4025. X    if (pcnt > 100) pcnt = 100;    /* (^_^) */
  4026. X#ifdef ANSI
  4027. X        printf ("\r%s%s - %s(%d%%)\n%s", CURSORUP, name, msg, pcnt, ERASEEOL);
  4028. X#else
  4029. X        printf ("\r%s - %s(%d%%)\n", name, msg, pcnt);
  4030. X#endif
  4031. X    fflush (stdout);
  4032. X}
  4033. X
  4034. Xfinish_indicator (name, msg)
  4035. X    char *name;
  4036. X    char *msg;
  4037. X{
  4038. X    if (quiet)
  4039. X        return;
  4040. X
  4041. X#ifdef ANSI
  4042. X        printf ("\r%s%s - %s\n%s", CURSORUP, name, msg, ERASEEOL);
  4043. X#else
  4044. X        printf ("\r%s - %s\n", name, msg);
  4045. X#endif
  4046. X    fflush (stdout);
  4047. X}
  4048. X
  4049. X
  4050. X#ifndef SELFMAIN
  4051. Xint encode_lzhuf (infp, outfp, size, original_size_var, packed_size_var, name)
  4052. X    FILE *infp;
  4053. X    FILE *outfp;
  4054. X    long size;
  4055. X    long *original_size_var;
  4056. X    long *packed_size_var;
  4057. X    char *name;
  4058. X{
  4059. X    infile = infp;
  4060. X    outfile = outfp;
  4061. X    SETUP_GETC_CRC(infp);
  4062. X    textsize = size;
  4063. X    codesize = 0;
  4064. X    init_crc ();
  4065. X    start_indicator (name, size, "Freezing");
  4066. X    Encode ();
  4067. X    finish_indicator2 (name, "Frozen",
  4068. X               (int)((codesize * 100L) / crc_size));
  4069. X    *packed_size_var = codesize;
  4070. X    *original_size_var = crc_size;
  4071. X    return crc_value;
  4072. X}
  4073. X
  4074. Xint decode_lzhuf (infp, outfp, original_size, name)
  4075. X    FILE *infp;
  4076. X    FILE *outfp;
  4077. X    long original_size;
  4078. X    char *name;
  4079. X{
  4080. X    infile = infp;
  4081. X    outfile = outfp;
  4082. X    SETUP_PUTC_CRC(outfp);
  4083. X    textsize = original_size;
  4084. X    init_crc ();
  4085. X        start_indicator (name, original_size,
  4086. X                         (output_to_test ? "Testing" : "Melting"));
  4087. X    Decode ();
  4088. X        finish_indicator (name, (output_to_test ? "Tested  " : "Melted  "));
  4089. X    return crc_value;
  4090. X}
  4091. X
  4092. X
  4093. Xint decode_larc (infp, outfp, original_size, name)
  4094. X    FILE *infp, *outfp;
  4095. X    long original_size;
  4096. X    char *name;
  4097. X{
  4098. X    infile = infp;
  4099. X    outfile = outfp;
  4100. X    SETUP_PUTC_CRC(outfp);
  4101. X    textsize = original_size;
  4102. X    init_crc ();
  4103. X        start_indicator (name, original_size,
  4104. X                         (output_to_test ? "Testing" : "Melting"));
  4105. X    DecodeOld ();
  4106. X        finish_indicator (name, (output_to_test ? "Tested  " : "Melted  "));
  4107. X    return crc_value;
  4108. X}
  4109. X#endif
  4110. X
  4111. X#ifdef SELFMAIN
  4112. Xint main (argc, argv)
  4113. X    int argc;
  4114. X    char *argv[];
  4115. X{
  4116. X    char  *s;
  4117. X    int i;
  4118. X
  4119. X    indicator_count = 0;
  4120. X    indicator_threshold = 1024;
  4121. X    textsize = codesize = 0;
  4122. X    if (argc != 4) {
  4123. X        printf ("\
  4124. Xusage: lzhuf e in_file out_file (packing)\n\
  4125. X       lzhuf d in_file out_file (unpacking)\n");
  4126. X        return EXIT_FAILURE;
  4127. X    }
  4128. X    if ((s = argv[1], ((*s != 'e') && (*s != 'd')) || s[1] != '\0') ||
  4129. X        (s = argv[2], (infile  = fopen(s, "rb")) == NULL) ||
  4130. X        (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
  4131. X        printf("??? %s\n", s);
  4132. X        return EXIT_FAILURE;
  4133. X    }
  4134. X    if (argv[1][0] == 'e') {
  4135. X        /* Get original text size and output it */
  4136. X        fseek(infile, 0L, 2);
  4137. X        textsize = ftell(infile);
  4138. X        rewind (infile);
  4139. X        if (fwrite(&textsize, sizeof textsize, 1, outfile) < 1)
  4140. X            Error("cannot write");
  4141. X
  4142. X        start_indicator (argv[2], textsize, "Freezing");
  4143. X        Encode();
  4144. X        finith_indicator2 (argv[2], "Frozen",
  4145. X                   (int)((codesize * 100L) / textsize));
  4146. X
  4147. X        printf("input : %ld bytes\n", textsize);
  4148. X        printf("output: %ld bytes\n", codesize);
  4149. X    } else {
  4150. X        /* Read original text size */
  4151. X        if (fread(&textsize, sizeof textsize, 1, infile) < 1)
  4152. X            Error("cannot read");
  4153. X
  4154. X        start_indicator (argv[2], textsize, "Melting");
  4155. X        Decode();
  4156. X        finish_indicator (argv[2], "Melted  ");
  4157. X    }
  4158. X    fclose(infile);
  4159. X    fclose(outfile);
  4160. X    return EXIT_SUCCESS;
  4161. X}
  4162. X#endif
  4163. X
  4164. X
  4165. X/* These lines are used in GNU-Emacs */
  4166. X/* Local Variables: */
  4167. X/* comment-column:40 */
  4168. X/* tab-width:8 */
  4169. X/* c-indent-level:8 */
  4170. X/* c-continued-statement-offset:8 */
  4171. X/* c-argdecl-indent:8 */
  4172. X/* End: */
  4173. END_OF_lzhuf.c
  4174. if test 22465 -ne `wc -c <lzhuf.c`; then
  4175.     echo shar: \"lzhuf.c\" unpacked with wrong size!
  4176. fi
  4177. # end of overwriting check
  4178. fi
  4179. if test -f makefile -a "${1}" != "-c" ; then 
  4180.   echo shar: Will not over-write existing file \"makefile\"
  4181. else
  4182. echo shar: Extracting \"makefile\" \(1707 characters\)
  4183. sed "s/^X//" >makefile <<'END_OF_makefile'
  4184. X# Makefile for LHArc UNIX
  4185. X#    Copyright(C) MCMLXXXIX  Yooichi.Tagawa
  4186. X# V0.01  Alpha Version                1989.05.28  Y.Tagawa
  4187. X# V0.02  Alpha Version R2            1989.05.29  Y.Tagawa
  4188. X# V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa
  4189. X
  4190. X#-----------------------------------------------------------------------
  4191. X# DIRECTORY ACCESS DEPENDENDS...
  4192. X#  The default (no need swtich) is your machine has
  4193. X#  opendir(),readdir(),closedir() library and 'direct' structure used.
  4194. X#  If your machine has no opendir (), readdir (), closedir ()
  4195. X#    -DNONSYSTEM_DIR_LIBRARY
  4196. X#  and add lhdir.o into OBJS macro (see bellow)
  4197. X#  If your machine are 'dirent' (not 'direct') structure used,
  4198. X#    -DSYSV_SYSTEM_DIR
  4199. X#  Otherwise "Give up!"
  4200. X#    -DNODIRECTORY
  4201. X#
  4202. X#-----------------------------------------------------------------------
  4203. X# MEMORY ACCESS STUFF
  4204. X#  Your machine has no BSTRING library (bcmp,bcopy,bzero).
  4205. X#    -DNOBSTRING
  4206. X#
  4207. X#-----------------------------------------------------------------------
  4208. X# TIME STUFF
  4209. X#  Your include file '<sys/time.h>' has no 'struct tm',  define this.
  4210. X#    -DSYSTIME_HAS_NO_TM
  4211. X#
  4212. X
  4213. X# most of 4.[23]BSD
  4214. X#    - vax 4.[23]BSD, SONY NEWS 4.[23]BSD etc.
  4215. X#SWITCHIES    =
  4216. X#OBJS        = lharc.o lzhuf.o lhio.o
  4217. X
  4218. X# sample of System-V
  4219. X#    - NEC EWS4800
  4220. X#-DSYSTIME_HAS_NO_TM
  4221. XSWITCHIES    = -DNOBSTRING -DSYSV_SYSTEM_DIR
  4222. XOBJS        = lharc.o lzhuf.o lhio.o rename.o
  4223. X
  4224. XCC        = cc
  4225. XCFLAGS        = $(SWITCHIES)
  4226. XLDFLAGS        = -ldir -lx
  4227. X
  4228. X#    Xlharc is test binary.  Please rename to lharc at install.
  4229. X#    (see install target)
  4230. Xall:    xlharc
  4231. X
  4232. Xxlharc    : $(OBJS)
  4233. X    $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS)
  4234. X
  4235. X#    For Debugging LzHuff module.
  4236. Xlzhuf    : lzhuf.c
  4237. X    $(CC) $(CFLAGS) -DSELFMAIN -o $* $*.c
  4238. X
  4239. Xlzhuf.o    lhio.o    : lhio.h
  4240. X
  4241. Xclean:
  4242. X    rm -f core lharc.o lzhuf.o lhdir.o lhio.o lharc.tar lharc.tar.Z
  4243. END_OF_makefile
  4244. if test 1707 -ne `wc -c <makefile`; then
  4245.     echo shar: \"makefile\" unpacked with wrong size!
  4246. fi
  4247. # end of overwriting check
  4248. fi
  4249. if test -f mktemp.c -a "${1}" != "-c" ; then 
  4250.   echo shar: Will not over-write existing file \"mktemp.c\"
  4251. else
  4252. echo shar: Extracting \"mktemp.c\" \(412 characters\)
  4253. sed "s/^X//" >mktemp.c <<'END_OF_mktemp.c'
  4254. X/* MKTEMP.C using TMP environment variable */
  4255. X
  4256. X#include <stdio.h>
  4257. X#include <stdlib.h>
  4258. X#include <string.h>
  4259. X#include <io.h>
  4260. X
  4261. Xvoid Mktemp(char *file)
  4262. X{
  4263. X  char fname[32], *tmp;
  4264. X
  4265. X  tmp = getenv("TMP");
  4266. X
  4267. X  if ( tmp != NULL )
  4268. X  {
  4269. X    strcpy(fname, file);
  4270. X    strcpy(file, tmp);
  4271. X
  4272. X    if ( file[strlen(file) - 1] != '\\' )
  4273. X      strcat(file, "\\");
  4274. X
  4275. X    strcat(file, fname);
  4276. X  }
  4277. X
  4278. X  mktemp(file);
  4279. X}
  4280. X
  4281. X/* End of MKTEMP.C */
  4282. END_OF_mktemp.c
  4283. if test 412 -ne `wc -c <mktemp.c`; then
  4284.     echo shar: \"mktemp.c\" unpacked with wrong size!
  4285. fi
  4286. # end of overwriting check
  4287. fi
  4288. if test -f pipes.c -a "${1}" != "-c" ; then 
  4289.   echo shar: Will not over-write existing file \"pipes.c\"
  4290. else
  4291. echo shar: Extracting \"pipes.c\" \(1116 characters\)
  4292. sed "s/^X//" >pipes.c <<'END_OF_pipes.c'
  4293. X/* a simulation for the Unix popen() and pclose() calls on MS-DOS */
  4294. X/* only one pipe can be open at a time */
  4295. X
  4296. X#include <stdio.h>
  4297. X#include <stdlib.h>
  4298. X#include <string.h>
  4299. X
  4300. Xstatic char pipename[128], command[128];
  4301. Xstatic int wrpipe;
  4302. X
  4303. Xextern void Mktemp(char *);
  4304. X
  4305. XFILE *popen(char *cmd, char *flags)
  4306. X{
  4307. X  wrpipe = (strchr(flags, 'w') != NULL);
  4308. X
  4309. X  if ( wrpipe )
  4310. X  {
  4311. X    strcpy(command, cmd);
  4312. X    strcpy(pipename, "~WXXXXXX");
  4313. X    Mktemp(pipename);
  4314. X    return fopen(pipename, flags);  /* ordinary file */
  4315. X  }
  4316. X  else
  4317. X  {
  4318. X    strcpy(pipename, "~RXXXXXX");
  4319. X    Mktemp(pipename);
  4320. X    strcpy(command, cmd);
  4321. X    strcat(command, ">");
  4322. X    strcat(command, pipename);
  4323. X    system(command);
  4324. X    return fopen(pipename, flags);  /* ordinary file */
  4325. X  }
  4326. X}
  4327. X
  4328. Xint pclose(FILE *pipe)
  4329. X{
  4330. X  int rc;
  4331. X
  4332. X  if ( fclose(pipe) == EOF )
  4333. X    return EOF;
  4334. X
  4335. X  if ( wrpipe )
  4336. X  {
  4337. X    if ( command[strlen(command) - 1] == '!' )
  4338. X      command[strlen(command) - 1] = 0;
  4339. X    else
  4340. X      strcat(command, "<");
  4341. X
  4342. X    strcat(command, pipename);
  4343. X    rc = system(command);
  4344. X    unlink(pipename);
  4345. X    return rc;
  4346. X  }
  4347. X  else
  4348. X  {
  4349. X    unlink(pipename);
  4350. X    return 0;
  4351. X  }
  4352. X}
  4353. END_OF_pipes.c
  4354. if test 1116 -ne `wc -c <pipes.c`; then
  4355.     echo shar: \"pipes.c\" unpacked with wrong size!
  4356. fi
  4357. # end of overwriting check
  4358. fi
  4359. if test -f readme -a "${1}" != "-c" ; then 
  4360.   echo shar: Will not over-write existing file \"readme\"
  4361. else
  4362. echo shar: Extracting \"readme\" \(1184 characters\)
  4363. sed "s/^X//" >readme <<'END_OF_readme'
  4364. X                                -*- Text -*-
  4365. X
  4366. XLHarc UNIX V0.03 Release #3  Beta Version
  4367. X
  4368. X    This is FREEWARE.  But it's BETA-VERSION.
  4369. X
  4370. X    Please reply to me.
  4371. X
  4372. X    Sorry, lharc.doc file are written in JAPANESE (Shift-JIS KANJI)
  4373. X
  4374. X                        Thank you.
  4375. X
  4376. X                        Yooichi.Tagawa
  4377. X                        Nikkei-MIX ID: y.tagawa
  4378. X------------------------------------------------------------------------
  4379. X
  4380. XHOW TO USE:
  4381. X    lharc {axevludmcp}[qnft] archive_file [files or directories...]
  4382. X
  4383. XCOMMAND:
  4384. X    KEY    MEANS                Like as (UNIX ar command)
  4385. X    --- ------------------------------    ------------------------------
  4386. X    a    Append to archive.              ar r AFILE files...
  4387. X    x,e  EXtract from archive.          ar x AFILE [files...]
  4388. X    v,l  View/List archive contents.      ar t AFILE [files...]
  4389. X    u    append newer files to archive.      ar ru AFILE files...
  4390. X    d    Delete from archive.          ar d AFILE files...
  4391. X    m    Move to archive.              ar m AFILE files...
  4392. X    c    re-construct new archive file.      rm AFILE; ar r AFILE files...
  4393. X    p    Print to STANDARD-OUTPUT          ar p AFILE [files...]
  4394. X
  4395. X
  4396. XOPTIONS:
  4397. X    q    quiet
  4398. X    n    no execute (debugging option)
  4399. X    f    force (over write at extract)
  4400. X    t    text-mode (this is provisional option)
  4401. X
  4402. X------------------------------------------------------------------------------
  4403. END_OF_readme
  4404. if test 1184 -ne `wc -c <readme`; then
  4405.     echo shar: \"readme\" unpacked with wrong size!
  4406. fi
  4407. # end of overwriting check
  4408. fi
  4409. if test -f rename.c -a "${1}" != "-c" ; then 
  4410.   echo shar: Will not over-write existing file \"rename.c\"
  4411. else
  4412. echo shar: Extracting \"rename.c\" \(1793 characters\)
  4413. sed "s/^X//" >rename.c <<'END_OF_rename.c'
  4414. X/*
  4415. X * $Author: chip $ $Date: 89/06/29 13:02:31 $
  4416. X * $Header: rename.c,v 1.1 89/06/29 13:02:31 chip Exp $
  4417. X * $Revision: 1.1 $
  4418. X */
  4419. X
  4420. X/*
  4421. X * Rename system call -- Replacement for Berzerkeley 4.2 rename system
  4422. X * call that is missing in Xenix.
  4423. X *
  4424. X * By Marc Frajola and Chris Paris.
  4425. X * Directory hack by Chip Salzenberg.
  4426. X */
  4427. X
  4428. X#include <stdio.h>
  4429. X#include <sys/types.h>
  4430. X#include <sys/stat.h>
  4431. X#include <signal.h>
  4432. X#include <errno.h>
  4433. X
  4434. Xrename(src,dest)
  4435. X    char *src;            /* Source file to rename */
  4436. X    char *dest;            /* Name for renamed file */
  4437. X{
  4438. X    int status;            /* Status returned from link system call */
  4439. X    struct stat stbuf;        /* Buffer for statting destination file */
  4440. X
  4441. X    /* Find out what the destination is: */
  4442. X    status = stat(dest,&stbuf);
  4443. X    if (status >= 0) {
  4444. X    /* See if the file is a regular file; if not, return error: */
  4445. X    if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
  4446. X        return(-1);
  4447. X    }
  4448. X    }
  4449. X
  4450. X    /* Unlink destination since it is a file: */
  4451. X    unlink(dest);
  4452. X
  4453. X    /* Find out what the source is: */
  4454. X    status = stat(src,&stbuf);
  4455. X    if (status < 0)
  4456. X    return -1;
  4457. X    if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
  4458. X    {
  4459. X    /* Directory hack for SCO Xenix */
  4460. X
  4461. X    static char mvdir[] = "/usr/lib/mv_dir";
  4462. X    void (*oldsigcld)();
  4463. X    int pid;
  4464. X
  4465. X    oldsigcld = signal(SIGCLD, SIG_DFL);
  4466. X    while ((pid = fork()) == -1)
  4467. X    {
  4468. X        if (errno != EAGAIN)
  4469. X        return -1;
  4470. X        sleep(5);
  4471. X    }
  4472. X    if (pid == 0)
  4473. X    {
  4474. X        execl(mvdir, mvdir, src, dest, (char *) 0);
  4475. X        perror(mvdir);
  4476. X        exit(1);
  4477. X    }
  4478. X    if (wait(&status) != pid)
  4479. X    {
  4480. X        fprintf(stderr, "rename: wait failure\n");
  4481. X        status = -1;
  4482. X    }
  4483. X    (void) signal(SIGCLD, oldsigcld);
  4484. X    }
  4485. X    else
  4486. X    {
  4487. X    /* Link source to destination file: */
  4488. X    status = link(src,dest);
  4489. X    if (status != 0) {
  4490. X        return(-1);
  4491. X    }
  4492. X    status = unlink(src);
  4493. X    }
  4494. X    return((status == 0) ? 0 : (-1));
  4495. X}
  4496. END_OF_rename.c
  4497. if test 1793 -ne `wc -c <rename.c`; then
  4498.     echo shar: \"rename.c\" unpacked with wrong size!
  4499. fi
  4500. # end of overwriting check
  4501. fi
  4502. echo shar: End of shell archive.
  4503. exit 0
  4504.  
  4505.  
  4506.