egray@fthood.UUCP (01/02/89)
Howdy netlanders... I've gotten a few request lately to post my version of the Arc v5.21 source that contains the squashing algorithm. This is part 1 (of 6) to the Arc v5.21 distribution package. This distribution of Arc v5.21 was derived almost entirely from work by Howard Chu (uunet!umix!hyc). This code includes the five offical patches (patch #1, patch #1b, patch #2, patch #2b, and patch #3). With the use of the preprocessor definition LOCAL, you can include my local enhancements and changes. The following changes were made: 1) By default, Unix file names are changed to meet MSDOS file name restrictions when added to an archive. Also, file names are folded to lowercase when extracted. This feature can be disabled by the use of the -z option. 2) Duplicate file names no longer cause a fatal error, the second file name is mearly skipped. This version is somewhat specific to the AT&T Unix PC 7300/3b1 (all the wierd stuff is in scandir.c and tmclock.c). Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Arc521.doc # This archive created: Sun Jan 1 12:48:03 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Arc521.doc'" '(54142 characters)' if test -f 'Arc521.doc' then echo shar: "will not over-write existing file 'Arc521.doc'" else sed 's/^X//' << \SHAR_EOF > 'Arc521.doc' X X X X X X X X X X X X X ARC X X File Archive Utility X Version 5.20 X X X X X X X X X X X X X X X X X X X X X X X X X X (C)COPYRIGHT 1985,86 X by X System Enhancement Associates, Inc. X ALL RIGHTS RESERVED X X X X X XThis document describes version 5.20 of the ARC file Xutility, which was created by System Enhancement XAssociates, Inc. in October of 1986. X X X TABLE OF CONTENTS X X X XSection Page X X XIntroduction .................................... 1 XUsing ARC ....................................... 3 XARC commands .................................... 5 X Adding files ................................ 5 X Extracting files ............................ 7 X Deleting files .............................. 8 X Listing archive entries ..................... 8 X Running files ............................... 10 X Printing files .............................. 11 X Testing an archive .......................... 11 X Converting an archive ....................... 12 XARC options ..................................... 13 X Suppressing compression ..................... 13 X Backup retention ............................ 14 X Message suppression ......................... 15 X Encryption/Decryption ....................... 17 XRAMdisk support ................................. 18 XMARC ............................................ 19 XARCE ............................................ 20 XVersion numbers ................................. 21 XCommon questions and answers .................... 22 XMaintenance contracts ........................... 24 XRevision history ................................ 25 X Changes in version 3 ........................ 25 X Changes in version 4 ........................ 25 X Changes in version 4.1 ...................... 26 X Changes in version 4.3 ...................... 26 X Changes in version 4.4 ...................... 27 X Changes in version 4.5 ...................... 27 X Changes in version 5.0 ...................... 28 X Changes in version 5.1 ...................... 29 X Changes in version 5.2 ...................... 30 XProgram history and credits ..................... 31 XBulletin boards ................................. 33 XSite licenses ................................... 34 X X X X X X X X X X X X X X INTRODUCTION X X X XARC is the copyrighted property of System Enhancement XAssociates, Inc. You are granted a limited license to Xuse ARC, and to copy it and distribute it, provided Xthat the following conditions are met: X X1) No fee may be charged for such copying and X distribution. X X2) ARC may ONLY be distributed in its original, X unmodified state. X X3) ARC may *not* be distributed, in whole or in part, as X part of any commercial product or service without X the express written permission of System X Enhancement Associates. X X XContributions for the use of this program will be Xappreciated, and should be sent to: X X System Enhancement Associates, Inc. X 21 New Street, Wayne NJ 07470 X XYou may not use this product in a commercial Xenvironment or a governmental organization without Xpaying a license fee of $35. Site licenses and Xcommercial distribution licenses are available. A Xprogram disk and printed documentation are available Xfor $50. See the order form enclosed with this manual Xfor more details. X X X XARC is user supported software. This means that you Xmay copy it freely and give the copies away to anyone Xyou wish, at no cost. They are in turn requested to Xsend in a contribution if they decide to use it. X XThe user supported software concept (often referred to Xas "shareware") is an attempt to provide software at low Xcost. The cost of offering a new product by Xconventional means is staggering, and hence dissuades Xmany independent authors and small companies from Xdeveloping and promoting their ideas. User supported Xsoftware is an attempt to develop a new marketing Xchannel, where products can be introduced at low cost. X X X X XARC Page 1 XIf user supported software works, then everyone will Xbenefit. The user will benefit by receiving quality Xproducts at low cost, and by being able to "test Xdrive" software thoroughly before purchasing it. The Xauthor benefits by being able to enter the commercial Xsoftware arena without first needing large sources of Xventure capital. X XBut it can only work with your support. We're not Xjust talking about ARC here, but about all user Xsupported software. If you obtain a user supported Xprogram from a friend or colleague, and are still Xusing it after a couple of weeks, then it is obviously Xworth something to you, and a contribution should be Xsent. X X X XAnd now, back to ARC: X XARC is used to create and maintain file archives. An Xarchive is a group of files collected together into Xone file in such a way that the individual files may Xbe recovered intact. X XARC is different from other archive and library Xutilities in that it automatically compresses the Xfiles being archived, so that the resulting archive Xtakes up a minimum amount of space. X XWhen ARC is used to add a file to an archive it Xanalyzes the file to determine which of three storage Xmethods will result in the greatest savings. These Xthree methods are: X X1) No compression; the file is stored as is. X X2) Repeated-character compression; repeated sequences X of the same byte value are collapsed into a three- X byte code sequence. X X3) Dynamic Lempel-Zev compression; the file is stored X as a series of variable size bit codes which X represent character strings, and which are created X "on the fly". X XNote that since one of the three methods involves no Xcompression at all, the resulting archive entry will Xnever be larger than the original file. X X X X X XARC Page 2 X USING ARC X X X XARC is invoked with a command of the following format: X X ARC <x> <arcname> [<template> . . .] X XWhere: X X <x> is an ARC command letter (see below), in X either upper or lower case. X X <arcname> is the name of the archive to act on, X with or without an extension. If no extension is X supplied, then ".ARC" is assumed. The archive X name may include path and drive specifiers. X X <template> is one or more file name templates. X The "wildcard" characters "*" and "?" may be used. X A file name template may include a path or drive X specifier, though it isn't always meaningful. X X XIf ARC is invoked with no arguments (by typing "ARC", Xand pressing "enter"), then a brief command summary is Xdisplayed. X X X XFollowing is a brief summary of the available ARC Xcommands: X X a = add files to archive X m = move files to archive X u = update files in archive X f = freshen files in archive X d = delete files from archive X x,e = extract files from archive X r = run files from archive X p = copy files from archive to standard output X l = list files in archive X v = verbose listing of files in archive X t = test archive integrity X c = convert entry to new packing method X X X X X X X X X XARC Page 3 XFollowing is a brief summary of the available ARC Xoptions, which may alter how a command works: X X b = retain backup copy of archive X s = suppress compression (store only) X w = suppress warning messages X n = suppress notes and comments X o = overwrite existing files when extracting X g = encode or decode archive entry X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XARC Page 4 X ARC COMMANDS X X X XThis section describes each of the commands. ARC will Xaccept any one command at a time. If no commands are Xgiven, then a brief command list is displayed. X X X XADDING FILES X XFiles are added to an archive using the "A" (Add), "M" X(Move), "U" (Update), or "F" (Freshen) commands. Add Xalways adds the file. Move differs from Add in that Xthe source file is deleted once it has been added to Xthe archive. X XUpdate differs from Add in that the file is only added Xif it is not already in the archive, or if it is newer Xthat the corresponding entry in the archive. X XFreshen is similar to Update, except that new files Xare not added to the archive; only files already in Xthe archive are updated. X X XFor example, if you wish to add a file named X"TEST.DAT" to an archive named "MY.ARC", you would use Xa command of the form: X X ARC a my test.dat X XIf you wanted to add all files with a ".C" extension, Xand all files named "STUFF" to an archive named X"JUNK.ARC", you could type: X X ARC a junk *.c stuff.* X XIf you wanted to move all files in your current Xdirectory into an archive named "SUM.ARC", you could Xuse a command of the form: X X ARC m sum *.* X XIf you have an archive named "TEXT.ARC", and you Xwanted to add to it all of your files with an Xextension of ".TXT" which have been created or changed Xsince they were last archived, then you would type: X X ARC u text *.txt X X X XARC Page 5 XIf you have a bunch of files in your current Xdirectory, with backup copies being stored in an Xarchive named "SAFE.ARC", then if you wanted to make Xsure that every file in the archive is the latest Xversion of that file, you would type: X X ARC f safe X X XA word about Update and Freshen: These are similar in Xthat they look at the date and time of last change on Xthe file, and only add it if the file has been changed Xsince it was last archived. They differ in that XUpdate will add new files, while Freshen will not. X XIn other words, Update looks for the files on disk, Xand adds them if they are new or have changed, while XFreshen looks in the archive, and tries to update the Xfiles which are already there. X X XArchive entries are always maintained in alphabetic Xorder. Archive entries may not have duplicate names. XIf you add a file to an archive that already contains Xa file by that name, then the existing entry in the Xarchive is replaced. Also, the archive itself and its Xbackup will not be added. X XYou may also add a file which is in a directory other Xthan your current directory. For example, it is Xperfectly legal to type: X X ARC a junk c:\dustbin\stuff.txt X XYou cannot add two files with the same name. In other Xwords, if you have a file named "C:\DUSTBIN\STUFF.TXT" Xand another file named "C:\BUCKET\STUFF.TXT", then Xtyping: X X arc a junk c:\dustbin\*.* c:\bucket\*.* X Xwill not work. X X XARC does not save the path name. In other words, if Xyou specify a drive and/or path when adding a file, Xonly the actual file name is stored in the archive. X X X X X X X XARC Page 6 XARC will never add an archive to itself, nor will it Xadd the temporary copy or a backup copy of the Xarchive. X X XAn interesting note: It has been brought to our Xattention that BASIC programs compress to a smaller Xsize when they are *not* tokenized. If you are more Xconcerned with space than speed, you may wish to Xconvert your BASIC programs to ASCII form before Xadding them to an archive. Your BASIC manual should Xgive instructions on how to do this. X X X XEXTRACTING FILES X XArchive entries are extracted with the "E" (Extract) Xand "X" (eXtract) commands. For example, if you had Xan archive named "JUNK.ARC", and you wanted all files Xin it with an extension of ".TXT" or ".DOC" to be Xrecreated on your disk, you could type: X X ARC x junk *.txt *.doc X XIf you wanted to extract all of the files in an Xarchive named "JUNK.ARC", you could simply type: X X ARC x junk X XWhatever method of file compression was used in Xstoring the files is reversed, and uncompressed copies Xare created in the current directory. X XYou can also specify a path name, in which case the Xdecompressed copy is placed in the specified Xdirectory. For example, if you had an archive named X"JUNK.ARC", and you wanted all files in it with an Xextension of ".TXT" to be placed in the directory X"C:\WASTE\LAND", then you could type: X X ARC x junk c:\waste\land\*.txt X XIf you wanted to put the file "TRASH.TXT" on your A: Xdrive, and the file "LITTER.TXT" on your B: drive, you Xcould type: X X ARC x junk a:trash.txt b:litter.txt X X X X X X XARC Page 7 XIf you give more than one path for a file, then only Xthe first one is used. For example, if you typed: X X ARC x junk a:trash.txt b:trash.txt X Xthen TRASH.TXT will be placed on your A: drive. X X X XDELETING FILES X XArchive entries are deleted with the "D" (Delete) Xcommand. For example, if you had an archive named X"JUNK.ARC", and you wished to delete all entries in it Xwith a filename extension of ".C", you could type: X X ARC d junk *.c X X X XLISTING ARCHIVE ENTRIES X XYou can obtain a list of the contents of an archive by Xusing the "L" (List) command or the "V" (Verbose list) Xcommand. For example, to see what is in an archive Xnamed "JUNK.ARC", you could type: X X ARC l junk X XIf you are only interested in files with an extension Xof ".DOC", then you could type: X X ARC l junk *.doc X X XARC prints a short listing of an archive's contents Xlike this: X X Name Length Date X ============ ======== ========= X ALPHA.TXT 6784 16 May 85 X BRAVO.TXT 2432 16 May 85 X COCO.TXT 256 16 May 85 X ==== ======== X Total 3 9472 X X X"Name" is simply the name of the file. X X X X X X XARC Page 8 X"Length" is the unpacked file length. In other words, Xit is the number of bytes of disk space which the file Xwould take up if it were extracted. X X"Date" is the date on which the file had last been Xmodified, as of the time when it was added to the Xarchive. X X"Total" is pretty obvious, I think. X X XARC prints a verbose listing of an archive's contents Xlike this: X XName Length Stowage SF Size now Date Time CRC X============ ======== ======== ==== ======== ========= ====== ==== XALPHA.TXT 6784 Crunched 35% 4413 16 May 85 11:53a 8708 XBRAVO.TXT 2432 Crunched 41% 1438 16 May 85 11:53a 5BD6 XCOCO.TXT 256 Packed 5% 244 16 May 85 11:53a 3AFB X ==== ======== ==== ======== XTotal 3 9472 27% 6095 X X X"Name", "Length", and "Date" are the same as for a Xshort listing. X X"Stowage" is the compression method used. The Xfollowing compression methods are currently known: X X -- No compression. X X Packed Runs of repeated byte values are X collapsed. X X Crunched Lempel-Zev compression technique X employed. X X Squeezed Huffman encoding compression X technique, as employed by an X earlier version of ARC. X X"SF" is the stowage factor. In other words, it is the Xpercentage of the file length which was saved by Xcompression. The total stowage factor is the stowage Xfactor for the archive as a whole, not counting Xarchive overhead. X X"Size now" is the number of bytes the file is Xoccupying while in the archive. X X X X X XARC Page 9 X"Time" is the time of last modification, and is Xassociated with the date of last modification. X X"CRC" is the CRC check value which has been stored Xwith the file. Another CRC value will be calculated Xwhen the file is extracted or tested to ensure data Xintegrity. There is no especially good reason for Xdisplaying this value. X X X XRUNNING FILES X XArchive entries may be run without being extracted by Xuse of the "R" (Run) command. For example, if you had Xan archive named "JUNK.ARC" which contained a file Xnamed "LEMON.COM", which you wished to run, you could Xtype: X X ARC r junk lemon X XYou can run any file from an archive which has an Xextension of ".COM", ".EXE", ".BAT", or ".BAS". You Xdo not have to specify the extension, but all matching Xfiles are run if you do not. In other words, if you Xhad an archive named "JUNK.ARC" which contained the Xfiles "LEMON.COM", "LEMON.EXE", and "LEMON.BAS", and Xyou typed: X X ARC r junk lemon X XThen all three programs will be run. You can avoid Xthis by specifying an extension in this case. X XYou can give arguments to the program you are running Xby appending them to the command line. For example, Xif you have an archive named "JUNK.ARC" which contains Xa program named "LEMON.COM", and you wanted to run it Xgiving it the argument "JUICE", you would type: X X ARC r junk lemon juice X XYou will need a fair amount of memory to run a program Xfrom an archive. It probably cannot be done with less Xthan 256k. X X X X X X X X X XARC Page 10 XIn practice, the file to be run is extracted, run, and Xthen deleted. In other words, the above example is Xequivalent to: X X ARC x junk lemon.com X lemon juice X erase lemon.com X XIf you have an archive which contains a program that Xyou will be running often, then you should probably Xextract the program from the archive and use it Xnormally. X X X XPRINTING FILES X XArchive entries may be examined with the "P" (Print) Xcommand. This works the same as the Extract command, Xexcept that the files are not created on disk. XInstead, the contents of the files are written to Xstandard output. For example, if you wanted to see Xthe contents of every ".TXT" file in an archive named X"JUNK.ARC", but didn't want them saved on disk, you Xcould type: X X ARC p junk *.txt X XIf you wanted them to be printed on your printer Xinstead of on your screen, you could type: X X ARC p junk *.txt >prn X X X XTESTING AN ARCHIVE X XThe integrity of an archive may be tested by use of Xthe "T" (Test) command. This checks to make sure that Xall of the file headers are properly placed, and that Xall of the files are in good shape. X XThis can be very useful for critical archives, where Xdata integrity must be assured. When an archive is Xtested, all of the entries in the archive are unpacked X(without saving them anywhere) so that a CRC check Xvalue may be calculated and compared with the recorded XCRC value. X X X X X X XARC Page 11 XFor example, if you just received an archive named X"JUNK.ARC" over a phone line, and you want to make Xsure that you received it properly, you could type: X X ARC t junk X XIt defeats the purpose of the T command to combine it Xwith N or W. X X X XCONVERTING AN ARCHIVE X XThe "C" (Convert) command is used to convert an Xarchive entry to take advantage of newer compression Xtechniques. This is occasionally desirable when a new Xversion of ARC is released. Please refer to the Xrevision history section for details on when new Xcompression methods were implemented. X XFor example, if you had an archive named "JUNK.ARC", Xand you wanted to make sure that all files with an Xextension of ".DOC" were encoded using the very latest Xmethods, you could type: X X ARC c junk *.doc X XOr if you wanted to convert every file in the archive, Xyou could type: X X ARC c junk X X X X X X X X X X X X X X X X X X X X X X X XARC Page 12 X ARC OPTIONS X X X XThis section describes the options which are available Xto modify how ARC works. Any of these options can be Xcombined with any of the commands, though the result Xmay not always be something you'd want to do. X X X XSUPPRESSING COMPRESSION X XThe "S" (Suppress compression) option can be combined Xwith any command that updates archive entries. These Xinclude Add, Move, Update, Freshen, and Convert. The Xeffect of the S option is to prevent any compression Xtechniques from being employed. This is intended to Xallow you to add a few files at a time to an archive Xquickly, and then later convert the archive to Xcompress everything at once. X XFor example, over the course of a day you might give Xeach of the following commands: X X ARC as junk *.txt X ARC as junk *.mac X ARC as junk *.doc X XAt the end of the day, when you have finished adding Xthings to the archive, you could have all of the Xarchive entries compressed at once by typing: X X ARC c junk X XYou could also decompress the archive by typing: X X ARC cs junk X Xthough I can't imagine why you'd want to. X X X X X X X X X X X X X X XARC Page 13 XBACKUP RETENTION X XWhen ARC changes an archive (during an Add, Move, XUpdate, Freshen, Delete, or Convert) it creates a new Xarchive with the same name, but with an extension of X".$$$". For example, if you add a file to an archive Xnamed STUFF.ARC, then ARC will create a new archive Xnamed STUFF.$$$. ARC will read from your existing Xarchive and write out the new archive with any changes Xto the ".$$$" copy. X XNormally when ARC is finished it deletes the original Xand renames the new archive to the original name (ie. XSTUFF.ARC goes away, and STUFF.$$$ becomes the new XSTUFF.ARC). Among other things, this means that if Xanything goes wrong and ARC is unable to finish, then Xyour original archive will still be intact. X X XIn some circumstances you may wish to retain the Xoriginal version of the archive as a backup copy. You Xcan do this easily by using the Backup option. Add Xthe letter "B" to your command, and ARC will rename Xyour original archive to have an extension of ".BAK" Xinstead of deleting it. X X XIn other words, if you wanted to add "WASTE.TXT" to an Xarchive named "JUNK.ARC", but wanted to keep a backup Xcopy, then you would type: X X ARC ab junk waste.txt X XYour original archive would become "JUNK.BAK", while X"JUNK.ARC" would contain the new "WASTE.TXT" file. X X XIf you keep a backup of an archive which already has a Xbackup, then the older backup copy is deleted. X X X X X X X X X X X X X X X XARC Page 14 XMESSAGE SUPPRESSION X XARC prints three types of messages: warnings, Xcomments, and errors. X XWarnings are messages about suspected error Xconditions, such as when a file to be extracted Xalready exists, or when an extracted file fails the XCRC error check. Warnings may be suppressed by use of Xthe "W" (Warn) command. You should use this command Xsparingly. In fact, you should probably not use this Xcommand at all. X XComments (or notes) are informative messages, such as Xnaming each file as it is added to the archive. XComments and notes may be suppressed by use of the "N" X(Note) command. X XErrors are actual system problems, such as running out Xof disk space. You cannot suppress errors. X X XFor example, suppose you extracted all files with an Xextension of ".BAS" from an archive named "JUNK.ARC" XThen, after making some changes which you decide not Xto keep, you decide that you want to extract them all Xagain, but you don't want to be asked to confirm every Xone. In this case, you could type: X X ARC xw junk *.bas X XOr, if you are going to add a hundred files with an Xextension of ".MSG" to an archive named "TRASH.ARC", Xand you don't want ARC to list them as it adds them, Xyou could type: X X ARC an trash *.msg X XOr, if you want to extract the entire contents of an Xarchive named "JUNK.ARC", and you don't want to hear Xanything, then type: X X ARC xnw junk X X XA special case is provided when extracting files from Xan archive. One of the various warnings that can Xoccur is when a file being extracted already exists on Xdisk. Normally, ARC will stop and ask you if you want Xto overwrite the file. This can be suppressed with Xthe "W" command, but that will also suppress any X X X XARC Page 15 Xwarnings about other things, like failed CRC checks Xand such. X XThe "O" (Overwrite) option suppresses *only* the warning Xthat the file already exists. For example, in our Xearlier case of extracting all the ".BAS" files from X"JUNK.ARC", a much safer way to do it is to type: X X ARC xo junk *.BAS X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XARC Page 16 XENCRYPTION/DECRYPTION X XArchive entries may be encrypted and decrypted by Xusing the "G" (Garble) option. The Garble option Xtakes the remainder of the command string as the Xpassword to use, so it must be the *last* option. X X XFor example, if you wanted to add a file named X"WASTE.TXT" to an archive named "JUNK.ARC", and you Xwanted to encrypt it using the password "DEBRIS", then Xyou would type: X X ARC agdebris junk waste.txt X XLater on, when you want to extract it again, you would Xtype: X X ARC xgdebris junk waste.txt X XThe password you supply is used to encrypt (or Xdecrypt) the archive entry by performing an exclusive XOR between each byte of the packed data and each byte Xof the password. The password can be any length, and Xeach of its bytes is used in rotation. The password Xis converted to uppercase before it is used, so it is X*not* case sensitive. Since the encryption is performed Xon the packed data, it has no effect on stowage Xfactors. X XThis is not a particularly sophisticated means of Xencryption, and it is theoretically possible to crack. XStill, since it is performed on the packed data, the Xresult should be quite sufficient for casual use. X X XYou can, if you wish, use different passwords for Xdifferent files in an archive, but we advise against Xit. If you are going to encrypt an archive, we Xsuggest you use the same password for every file, and Xgive the password whenever you do anything at all with Xthe archive. It is possible to list the entries in an Xencrypted archive using the "L" and "V" commands Xwithout giving the password, but nothing else will Xwork properly. X X XWe advise that you use this option sparingly, if at Xall. If you should forget or mistype your password, Xit is highly unlikely that you will ever recover your Xdata. X X X XARC Page 17 X RAMDISK SUPPORT X X X XIf you have a RAMdisk, or other high-speed storage, Xthen you can speed up ARC somewhat by telling it to Xput its temporary files on the RAMdisk. You do this Xby setting the ARCTEMP environment string with the MS- XDOS SET command. For example, if drive B: is your XRAMdisk, then you would type: X X set ARCTEMP=B: X XRefer to the MS-DOS manual for more details about the XSET command. You need only set the ARCTEMP string Xonce, and ARC will use it from then on until you Xchange its value or reboot your system. X X XIf ARC does not find an environment string named XARCTEMP, then it looks for one named TEMP to use Xinstead. Several packages already use the TEMP string Xfor exactly this purpose. If you have need of an Xenvironment string named TEMP for something else, then Xyou should be sure to define ARCTEMP. X X XThere are a limited number of temporary files created Xby ARC. The Convert command uses a file named X"$ARCTEMP.CVT" to hold each file as it is being Xconverted. The Run command also creates a temporary Xfile, which has the name "$ARCTEMP", and whose Xextension matches that of the file being run. X X X X X X X X X X X X X X X X X X X X X XARC Page 18 X MARC X X X XMARC is a separate program which is used to merge Xarchives created by ARC. MARC moves files from one Xarchive to another without unpacking them. X X XMARC is used as follows: X X MARC <target> <source> [<template> . . .] X XWhere: X X <target> is the name of the archive to add files X to. X X <source> is the name of the archive to read files X from. X X <template> is one or more file name templates. X The wildcard characters "*" and "?" may be used. X If no template is supplied, then all of the files X in <source> are added to <target>. X XIt is not necessary for the target to exist. If it Xdoes not exist, then it is created. Thus, MARC can be Xused as an "extractor" as well as a "merger". X X XFor example, if you wanted to create an archive named X"JUNK.ARC", which is to contain all of the files with Xan extension of ".TXT" which are currently contained Xin another archive named "WASTE.ARC", then you could Xtype: X X MARC junk waste *.txt X XIf you wanted to create an archive named "JUNK.ARC", Xwhich is to contain all of the files currently in the Xarchives "WASTE.ARC" and "TRASH.ARC", you could type: X X MARC junk waste X MARC junk trash X X XIf MARC is invoked with no arguments, then it gives Xbrief directions in its use. X X X X X XARC Page 19 X ARCE X X X XARCE is a program which is used to extract files from Xan archive. It will *only* extract files, and it will X*not* extract encrypted files. It doesn't do anything Xthat ARC can't do, but it is highly optimized for the Xsole purpose of archive extraction, so it is very Xsmall and very fast. X XARCE is used in a fashion very similar to the "ARC E" Xcommand (hence the name). The first argument is the Xname of the archive to extract files from, and may Xinclude a drive and path specifier. Up to sixteen Xadditional arguments can be supplied, which specify Xthe files to extract. The wildcard characters "*" and X"?" are allowed, as with ARC. If no files are named, Xthen all files are extracted from the archive. If the Xfile being extracted already exists, you are asked Xwhether or not you want to overwrite it. You can use Xthe "/R" option to bypass this. X XFor example, if you had an archive named "WASTE.ARC" Xthat you wanted to extract everything from, then you Xcould type: X X ARCE waste X XOr if you just wanted to extract the files with a Xfilename extension of ".ASM", you could type: X X ARCE waste *.asm X XIf you already have a few files from the archive that Xyou want replaced, then you could type: X X ARCE waste *.asm /R X XIf you run ARCE with no arguments at all, then it will Xgive you a brief reminder of how to use it. X X XNOTICE:NOTICE: ARCE is the copyrighted property of Vernon D. X Buerg and Wayne Chin. It is included on the X ARC program disk as a service to ARC users. X X Vernon D. Buerg X 456 Lakeshire Drive X Daly City, CA 94015 X RBBS: (415) 994-2944 X X X XARC Page 20 X VERSION NUMBERS X X X XThere seems to be some confusion about our version Xnumbering scheme. All of our version numbers are Xgiven as a number with two decimal places. X XThe units indicate a major revision, such as adding a Xnew packing algorithm. X XThe first decimal place (tenths) indicates a minor Xrevision that is not essential, but which may be Xdesired. X XThe second decimal place (hundredths) indicates a Xtrivial revision that will probably only be desired by Xspecific individuals or by die-hard "latest version" Xfanatics. X XARC also displays its date and time of last edit. A Xchange of the date and time without a corresponding Xchange in version number indicates a truly trivial Xchange, such as fixing a spelling error. X X XTo sum up: If the units change, then you should get Xthe newer version as soon as you can. If the tenths Xchange, then you may want to get the newer version, Xbut there's no hurry. If anything else changes, then Xyou probably shouldn't bother. X X X X X X X X X X X X X X X X X X X X X X X XARC Page 21 X COMMON QUESTIONS AND ANSWERS X X X XHere are some of the more common questions we've Xreceived about ARC, along with their answers: X X XQ: Why does ARC run out of room if I make an archive X bigger than about 180k? X XA: Because you are working on a floppy disk. ARC X creates a copy of your archive, incorporating any X new files as it goes. When it is done, it deletes X the original and renames the new one. There are a X number of reasons for doing it this way, one being X that your original archive is still intact if X anything happens while ARC is running. X X You can save some space by using drive specifiers X and having the archive and the files to add on X separate disks, but you still won't be able to make X an archive larger than about 180k. If you need to X make a larger archive, and if you have a fixed X disk, then you can create the archive on the fixed X disk and then copy it to the floppy. X X XQ: I've seen an ARC.COM and an ARC.EXE. Which one is X the right one? X XA: ARC.EXE. One or more people have been running ARC X through a utility that converts an ".EXE" file to a X ".COM" file. But this utility is designed to save X space, not speed. On ARC it saves about 250 bytes, X and makes no measurable difference in program X speed. We've decided that the savings are not X worth the extra step in development in this case. X X XQ: How can I get the latest version of ARC? X XA: ARC updates are distributed through normal X shareware channels, and by FidoNet. We also ship a X program update disk on every order of $50 or more. X Also, please refer to the next section for X information about our maintenance contracts. X X X X X X X XARC Page 22 XQ: Can I use ARC to distribute my public domain or X shareware program? X XA: Yes, of course. X X XQ: Can I use ARC to distribute my commercial software X package? X XA: Yes, provided that you obtain a commercial X distribution license from us. Please contact us X for details. X X XQ: I'm a commercial user. Why should I pay for X shareware that others get for free? X XA: Because you cannot credibly plead poverty. X ___ Shareware, all shareware, is an attempt to develop X a new marketing channel to the benefit of everyone. X You can still "test drive" shareware for a short X period, but if you decide to use it in your X business, then you should pay for it. X X XQ: Why not allow me to select which method of X compression I want ARC to use? X XA: It would needlessly complicate ARC, both internally X and in use. The exact nature of the compression X methods used are complex, and quite different. The X only sure way to tell which will be best in any X given case is to analyze the data, as ARC does. X The method chosen may not always be what you X expect. X X X X X X X X X X X X X X X X X X X XARC Page 23 X MAINTENANCE CONTRACTS X X X XRegistered users of ARC receive 90 days of telephone Xsupport at no extra charge. If you wish, you can Xextend this by pruchasing a maintenance contract. X XA maintenance contract costs $50 per year and entitles Xyou to unlimited telephone support, as well as free Xupdates to ARC as they come out. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XARC Page 24 X REVISION HISTORY X X X XCHANGES IN VERSION 3 X XThe function used to calculate the CRC check value in Xprevious versions has been found to be in error. It Xhas been replaced with the proper function. ARC will Xstill read archives created with earlier versions of XARC, but it will report a warning that the CRC value Xis in error. All archives created prior to version X3.0 should be unpacked and repacked with the latest Xversion of ARC. X X XTransmitting a file with XMODEM protocol rounds the Xsize up to the next multiple of 128 bytes, adding Xgarbage to the end of the file. This used to confuse XARC, causing it to think that the end of the archive Xwas invalidly formatted. This has been corrected in Xversion 3.01. Older archives may still be read, but XARC may report them to be improperly formatted. All Xfiles can be extracted, and no data is lost. In Xaddition, ARC will automatically correct the problem Xwhen it is encountered. X X X XCHANGES IN VERSION 4 X XARC is adding another data compression technique in Xthis version. We have been looking for some technique Xthat could improve on Huffman squeezing in at least a Xfew cases. So far, Lempel-Zev compression seems to be Xfulfilling our fondest hopes, often achieving Xcompression rates as much as 20% better than Xsqueezing, and sometimes even better. Huffman Xsqueezing depends on some bytes being more "popular" Xthan others, taking the file as a whole. Lempel-Zev Xcompression is instead looking for strings of bytes Xwhich are repeated at various points (such as an end Xof line followed by spaces for indentation). Lempel- XZev compression is therefore looking for repetition at Xa more "macro" level, often achieving impressive Xpacking rates. X XIn the typical case a file is added to an archive once Xand then extracted many times, so the increased time Xfor an update should more than pay for itself in Xincreased disk space and reduced transmission time. X X X XARC Page 25 XCHANGES IN VERSION 4.1 X XLempel-Zev coding has been improved somewhat by Xperforming non-repeat compression on the data before Xit is coded (as was already done with Huffman Xsqueezing). This has the two fold advantage of (a) Xreducing to some extent the amount of data to be Xencoded, and (b) increasing the time it takes for the Xstring table to fill up. Performance gains are small, Xbut noticeable. X XThe primary changes are in internal organization. ARC Xis now much "cleaner" inside. In addition to the Xaesthetic benefits to the author, this should make Xlife easier for the hackers out there. There is also Xa slight, but not noticeable, improvement in overall Xspeed when doing an update. X X X XCHANGES IN VERSION 4.3 X XVersion 4.3 adds the much-demanded feature of using Xpathnames when adding files to an archive. X XVersion 4.3 is also using a slightly different Xapproach when adding a file to an archive. The end Xresult is twofold: X X1) Slightly more disk space is required on the drive X containing the archive. This should only be X noticeable to those creating very large archives on X a floppy based system. X X2) A 30% reduction in packing time has been achieved X in most cases. This should be noticeable to X everyone. X XAs always, version 4.3 is still fully upwards Xcompatible, and is backwards compatible as far as Xversion 4.1. X X X X X X X X X X X X X XARC Page 26 XCHANGES IN VERSION 4.4 X XThe temporary file introduced in version 4.3 Xoccasionally caused problems for people who had not Xadded a FILES= statement to their CONFIG.SYS file. XThis has now been corrected. Also, support of the XARCTEMP environment string was added to allow placing Xof the temporary file on a RAMdisk. X XA bug was reported in the Run command, which has been Xfixed. From the nature of the bug, and the extreme Xtime required before the bug was reported, it is Xdeduced that the Run command is probably the least Xused feature of ARC. X XThe Update command was changed. It is no longer a Xstraight synonym for Add. Instead, Update now only Xadds a file if it is newer than the version already in Xthe archive, as shown by the MS-DOS date/time stamp. X X X XCHANGES IN VERSION 4.5 X XThe Convert command was not making use of RAMdisk Xsupport. Now it is. X XThe Freshen command was added. Our first choice for a Xname was Refresh, but we already had a Run command. XAssuming that you have an archive which already Xcontains everything you want in it (for software Xdistribution, perhaps), then Freshen would be used to Xupdate the archive. It was pointed out to us that ARC Xalready knows what is in the archive, so it should be Xable to look on disk for newer versions. Now it can. X XThe Suppress compression option was added by popular Xdemand. It allows files to be added quickly to an Xarchive, since the files are not analyzed or Xcompressed, but merely stored straight. The intent is Xto allow users to build an archive "in pieces", and Xthen compress all of the entries at once with the XConvert command. The conversion is much faster if you Xtake advantage of RAMdisk support. X XA minor bug was detected in our handling of date/time Xstamps which occasionally resulted in stamping an Xarchive with the wrong date and time. This has been Xcorrected. X X X X X XARC Page 27 XCHANGES IN VERSION 5.0 X XThe Move command used to delete the files as it went. XIt now waits until it is finished updating the Xarchive, and deletes them all at once. (You *did* know Xthat Move is just an Add where the file gets deleted, Xdidn't you?) This, along with the changes made in Xversion 4.5, means that it is now much safer to Xinterrupt ARC while it is working. X XThe Print command no longer prints the name of each Xfile. Instead, it prints a formfeed after each file. X XThe Run command now supports BASICA programs. Also, Xthe filename extension is no longer required on the XRun command. X XThe Garble option was added. It provides a convenient Xmeans of low level data security for the casual user. XUse it sparingly, if at all. X XARC no longer tests for the presence of $ARCTEMP.CRN Xbefore creating a new one. If you interrupt ARC a Xlot, you'll find this much more convenient. If you Xhappen to have a file named $ARCTEMP.CRN which you Xwant to keep, too bad. X XImproved error recovery was added when reading an Xarchive. ARC now has a good chance of recovering the Xdata from a corrupted archive (the corrupted entry is Xstill lost, of course). X XPath support has been added for all commands, though Xit doesn't do anything on most of them. For example, Xthere isn't much we can do with a path in the List Xcommand. But many users will be glad to know that a Xpath can be used when extracting a file, and specifies Xwhere the file is to be placed. X XSupport for the TEMP environment string was added. If XARC doesn't find an environment string named ARCTEMP, Xthen it looks for one named TEMP to use instead. XSeveral packages already use the TEMP string for Xexactly this purpose. With any luck, maybe we can get Xa standard going. X X X X X X X X X XARC Page 28 XARC is now using a different variation of Lempel-Zev Xcoding, courtesy of Kent Williams, who found it on XUSENET and adapted it to the IBM PC. The new method Xdiffers from the old in several respects. The most Xsignificant differences are: X X1) Where our previous implementation used a fixed code X size of twelve bits, the new one starts with a code X size of nine bits and increases it as it needs to. X X2) The earlier method tended to "choke" on large files X when its string table filled up. The new method X has a rather ingenious scheme its authors call X "adaptive reset." When it notices that its string X table has filled, and its compression ratio is X starting to suffer, it clears the table and starts X defining new strings. X XOur benchmarks show an improvement in compression on Xthe order of 10% when crunching is used. XAdditionally, ARC 5.0 is on the order of 23% faster at Xadding a file when crunching is used, or 13% faster Xwhen squeezing is used. Extracting a file crunched Xwith the new method is 27% faster than it is with the Xold method. Extraction of any other type of file X(including those crunched with the older method) is no Xfaster than before. These figures are based on our Xown benchmark tests; your results may vary. X XThe previous implementation of Lempel-Zev coding is no Xlonger used to pack files. The "V" (Verbose listing) Xcommand distinguishes between the two by referring to Xthe older method as "crunched" (with a lower-case X"c"), and the newer method as "Crunched" (with a Xcapital "C"). X XARC 5.0 can still read archives created by earlier Xversions of ARC, but once again it creates archives Xwhich older versions cannot read. X X X XCHANGES IN VERSION 5.1 X XRick Moore discovered that ARC was occasionally adding Xan archive to itself. This would only happen when the Xarchive is in the same directory as the files being Xadded, and its name comes last. This bug has been Xfixed, though it is still possible to fool ARC into Xadding an archive to itself by getting tricky with Xpath names. X X X XARC Page 29 XDana Montgomery found the upper limit on how many Xfiles can be added to an archive. There's always been Xan upper limit, but it depends on memory, and used to Xbe larger than anyone could possibly want (knock on Xwood). However, the added memory requirements in Xversion 5.0 lowered this limit into the realm of Xpossibility, somewhere around 300 files. We change Xsome things around, and effectively, there is no Xlonger a limit on how many files you can add at once. XARC will add the files in batches of as many as it can Xhandle at one time. X XWe've also introduced a new packaging method for ARC Xand its documentation, since we are in the unique Xposition of being unable to use ARC for this purpose. XWe've created a program called ARC51.COM which, when Xexecuted, attempts to create the ARC program and Xmanual. You must be in the same directory as XARC51.COM when you run it. X X X XCHANGES IN VERSION 5.2 X XWe've made some changes to Lempel-Zev coding to Xfurther improve its compression ability on "poor fit" Xfiles (mainly .EXE and .COM files). The result is Xthat crunching now works better than squeezing on Xalmost all files, and comes close on most of the rest X(within 5%, by our benchmarks). Accordingly, we have Xdropped Huffman encoding in this version. Our Xbenchmarks show a speed improvement of around 14% when Xadding a file to an archive. X XA low-level file copy routine was implemented to speed Xup bulk data moves. Deleting or adding a file to a Xlarge existing archive is now much faster. X XThe Run command has been modified to allow passing Xcommand line arguments to the program being run. X XThe temporary file introduced in version 4.3 has been Xeliminated. Crunched output generated in the analysis Xphase is now placed directly in the output archive, Xand is rewritten if crunching turns out not to be the Xbest choice. This can, in rare circumstances, cause Xan archive to be slightly larger than it should be, Xbut it also makes ARC considerably faster at adding Xfiles to an archive. X X X X X XARC Page 30 X PROGRAM HISTORY AND CREDITS X X X XIn its short life thus far, ARC has astounded us with Xits popularity. We first wrote it in March of 1985 Xbecause we wanted an archive utility that used a Xdistributive directory approach, since this has Xcertain advantages over the then popular central Xdirectory approach. We added automatic squeezing in Xversion 2 at the prompting of a friend. In version X2.1 we added the code to test for the best compression Xmethod. In less than a year we found that our humble Xlittle program had spread across the country, and Xseems to have become a new institution. X XWe are thankful for the support and appreciation we Xhave received. We hope that you find this program of Xuse. X X XIf we have achieved greatness, it is because we have Xstood upon the shoulders of giants. Nothing is Xcreated as a thing unto itself, and ARC is no Xexception. Therefore, we would like to give credit to Xthe following people, without whose efforts ARC could Xnot exist: X X XBrian W. Kernighan and P. J. Plauger, whose book X"Software Tools" provided many of the ideas behind the Xdistributive directory approach used by ARC. X XDick Greenlaw, who wrote the public domain SQ and USQ Xprograms, in which the Huffman squeezing algorithm was Xfirst developed. X XRobert J. Beilstein, who adapted SQ and USQ to XComputer Innovations C86 (the language we use), thus Xproviding us with important parts of our squeezing Xlogic. X XKent Williams, who graciously allowed us to use his XLZWCOM and LZWUNC programs as a basis for our Lempel- XZev compression logic, and who continues to make Xvaluable contributions. X XDavid Schwaderer, whose article in the April 1985 Xissue of PC Tech Journal provided us with the logic Xfor calculating the CRC 16 bit polynomial. X X X X XARC Page 31 XTerry A. Welch, whose article "A Technique for High XPerformance Data Compression", IEEE Computer Vol 17 No X6 (June 1984) seems to have started all the research Xon Lempel-Zev coding. X XSpencer W. Thomas, Jim McKie, Steve Davies, Ken XTurkowski, James A. Woods, and Joe Orost, who are the Xauthors of the UNIX compress utility. X XAlex Jacobs, who in June of 1985 sent us the very Xfirst shareware contribution we ever received. X X XAnd many, many others whom we could not identify. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XARC Page 32 X BULLETIN BOARDS X X X XARC is distributed mainly through shareware channels. XAmong other things, this means that ARC is available Xfrom many bulletin board systems. In fact, the system Xoperators (sysops) of many bulletin boards have taken Xto storing almost all of their downloadable files in Xarchives to save themselves disk space and to save Xtheir users time. X XThis also makes things more convenient for the Xbulletin board users, since one archive may contain Xseveral programs, any related data files, and the Xdocumentation. Many shareware authors have taken to Xdistributing their software in archives to help ensure Xthat the users receive everything. X XObviously, we can't do that with ARC. As a result, Xmany of our users have ARC, but don't have the manual. XMost of our customer support calls come from people Xwho have never seen the manual, and in many cases Xdidn't even know that one exists! X XTo solve this problem we developed what is in essence Xa self-unpacking archive. We distribute this as X"ARCxxx.COM", where "xxx" is the current version Xnumber. For example, ARC version 5.20 would be Xdistributed as "ARC520.COM". This program, when run, Xunpacks itself into a copy of ARC plus its Xdocumentation. X XNow that we've gone to all that work, we'd really Xappreciate it if you would use this program when you Xdistribute ARC. X X X X X X X X X X X X X X X X X X XARC Page 33 X SITE LICENSES X X X XCorporate users may wish to obtain a site license for Xthe use of ARC. Please use the order form in this Xmanual to order a site license. Site licenses are Xgranted as of when we receive your payment. License Xfees vary depending on the number of computers on Xwhich ARC will be used, as follows: X X 1 to 9 machines $35 each X 10 to 24 machines $25 each X 25 to 49 machines $20 each X 50 to 99 machines $15 each X over 99 machines $1500 one time fee X X X XEnclosed is a site license agreement, which should be Xsigned and sent with your payment when ordering a Xcommercial site license. X X XA commercial site license does not include additional Xcopies of the ARC program disk and the ARC manual. XInstead, you make your own copies of the disk and Xmanual as you need them. If you wish, you can order Xadditional program disks and manuals from us. X XAdditional program disks cost $10 each. Additional Xmanuals cost $20 each. If you wish, you can order Xprogram sets for $40 each. A "program set" is a Xprogram disk and manual enclosed in a vinyl binder. XThere is a $50 minimum on all orders. X X X X X X X X X X X X X X X X X X X XARC Page 34 X SITE LICENSE APPLICATION X X X XThe use of ARC in a commercial environment or government organization Xis granted under the following terms: X X1. Payment of the license fee must be made to System Enhancement X Associates, Inc. The fee is based on the number of computers X which will be used to run ARC, as follows: X X 1 to 9 machines $35 each X 10 to 24 machines $25 each X 25 to 49 machines $20 each X 50 to 99 machines $15 each X over 99 machines $1500 one time fee X X2. You may use ARC on the number of computers included in the license X fee. If you have paid the fee for over 99 machines, then you may X use ARC on any number of computers within your organization. X X3. You may make copies of the program and documentation, in their X original, unmodified form, without restriction. You may X distribute these copies without restriction. X X4. If these copies are distributed outside of your organization, you X have no obligation to control the use of those copies which are X outside of your organization. X X5. You may make copies of the program documentation, in both its X printed form and machine readable form, without restriction. X X6. You may use all future versions of ARC under this license. X X7. You may *not* modify the program or charge a fee for copying or X distributing the program or its documentation. X X8. It is your responsibility to make the necessary copies and to X deliver them to the computers which they will be used on. If you X wish, you can order additional ARC program disks and manuals. X X9. We are not responsible for *anything* that may happen or not happen X if you use ARC. You're on your own. X X X I agree to abide by the terms and conditions of this license. X X _____________________________ __________________________ X Signature Date X X _____________________________ X Name (please print or type) X X _____________________________ X Title X X _____________________________ X Company X X X ORDER FORM X X X XCheck which items you wish to purchase: X X [] Noncommercial license for the use of ARC. X X [] Commercial license for the use of ARC on ___ computers (see X attached price schedule and terms). X X [] Program disk and documentation (only on orders of $50 or more, X not counting maintenance contracts). X X [] ____ additional program disks at $10 per disk. X X [] ____ additional manuals at $20 per manual X X [] ____ additional program sets (disk, manual, and binder) at $40 X per program set. X X [] One year maintenance agreement at $50 per year. X X [] Payment of $_____ is enclosed (check or money order). X X [] Please charge $_____ to my [] Visa or [] MasterCard: X X Card number: _______________________________ X X Expiration date: ___________________________ X X Signature: _________________________________ X X _______________________________________________ X Name X X _______________________________________________ X X X _______________________________________________ X Address X X ______________________ ________ ____________ X City State Zip X X _______/_______ X FidoNet address X X XSend this completed form to: X X System Enhancement Associates, Inc. X 21 New Street, Wayne NJ 07470 X XFor program disk orders outside the U.S., please add an additional $5, Xand enclose an international money order payable in U.S. currency. X XFor commercial site license orders, please enclose a signed copy of Xthe site license agreement. X SHAR_EOF if test 54142 -ne "`wc -c < 'Arc521.doc'`" then echo shar: "error transmitting 'Arc521.doc'" '(should have been 54142 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (01/02/89)
This is part 2 (of 6) to the Arc v5.21 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Arc.1 # Arcinfo # Changes.521 # Makefile # Manifest # README # Read.me # Readme.local # Readme.too # arc.c # arc.h # This archive created: Sun Jan 1 12:48:09 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Arc.1'" '(7232 characters)' if test -f 'Arc.1' then echo shar: "will not over-write existing file 'Arc.1'" else sed 's/^X//' << \SHAR_EOF > 'Arc.1' X.TH ARC 1L "12 Jun 1988" "Local" "LOCAL COMMANDS" X.SH NAME Xarc \- pc archive utility X.SH SYNOPSIS X.B arc Xa|m|u|f|d|x|e|r|p|l|v|t|c [ biswnoq ] [ g\fIpassword\fR ] X.I archive X[ \fIfilename\fR ...] X.SH DESCRIPTION X.I Arc Xis a general archive and file compression utility, used to maintain Xa compressed archive of files. XAn X.I archive Xis a single file that combines many files, reducing storage space Xand allowing multiple files to be handled as one. X.I Arc Xuses one of several compression methods for each file within the X.IR archive , Xbased on whichever method yields the smallest result. X.SH INSTRUCTIONS XExecute X.I arc Xwith no arguments for fairly verbose, usable instructions. X.SH COMMAND SWITCHES X.TP 3 Xa Xadd files to archive. Copies the indicated files to the archive. X.TP Xm Xmove files to archive. Same as 'a' switch except Xthat the files are deleted from the directory as Xthey are moved to the archive. X.TP Xu Xupdate files in archive. This switch will replace archived Xfiles when the named file is newer than the archived copy. XNew files will be added automatically. X.TP Xf Xfreshen files in archive. Same as 'u' except that Xnew files will not be added. X.TP Xd Xdelete files in archive. The named files are removed from the archive. X.TP Xx,e Xextract files from archive. The named files are extracted Xfrom the archive and created in the current directory Xin an uncompressed state. X.TP Xr Xrun one file with arguments from archive. Any Xprogram may be executed directly from the archive. XThe parameters given after the program name are passed to Xthe program without modification. X.TP Xp Xcopy files from archive to standard output. Useful Xwith I/O redirection. A form-feed is appended after each file, Xto ease use with printers. X.TP Xl Xlist files in archive. Limited information listing Xof files contained in an archive. Displays the Xfilename, original length, and date last modified. XIf the 'n' option (see below) is used, only the Xfilename is displayed. X.TP Xv Xverbose listing of files in archive. Complete Xinformation listing of files contained in an archive. XDisplays the filename, original length, storage method, Xstorage factor (% savings), compressed size, date, time, Xand CRC. X.TP Xt Xtest archive integrity. Computes CRC values for each member of Xthe archive and compares against the previously saved value. X.TP Xc Xconvert entry to new packing method. Convert files Xstored with older methods to newer methods that are Xmore efficient. Also useful for files previously Xarchived with the 's' option. X.SH OPTIONS X.TP 3 Xb Xretain backup copy of archive. Keep the original Xarchive file and rename to .BAK. XThis switch may be used with the Xfollowing commands: a, m, u, f, d, c. X.TP Xi Xsuppress image mode. This switch causes files to Xbe treated as text files, and will translate their Xend-of-line sequence. (Unix's '\\n' vs. '\\r\\n' used Xon many other systems.) The default is to perform Xno translation when compressing or extracting files. XThis option makes dealing with text files much nicer, Xthough the 'tr' command can also be used. ('\\r' in Xmakefiles and C source code is such a nuisance...) X.TP Xs Xsuppress compression. This forces new files to be Xsaved using Method 2 (no compression). This switch Xmay be used with the following commands: a, m, u, f, c. X.TP Xw Xsuppress warning messages. This switch will keep Xwarning messages from being displayed which is the default. XMost warnings concern the deletion or existence of Xfiles with the same name. X.TP Xn Xsuppress notes and comments. This switch will keep Xuseful notes from being displayed which is the default. XMost notes indicate what stage of compression is Xbeing run (analyze, compaction, storage). X.TP Xo Xoverwrite existing files when extracting. This switch Xwill make existing files silently get overwritten, instead Xof asking for confirmation, which is the default. X.TP Xq Xforce Squash compression method. This switch causes Xthe Squash compression method to be used, instead of XCrunch, which is the default. X.TP Xg Xencrypt/decrypt archive entry. This is used to encode Xfiles so that others may not read them. BE CAREFUL! XThis must be the last parameter in the switches because Xeverything following is part of the password. X.SH PROGRAMMING NOTES X.I Arc XVersion 2 differs from version 1 in that archive entries Xare automatically compressed when they are added to the archive, Xmaking a separate compression step unecessary. The nature of the Xcompression is indicated by the header version number placed in Xeach archive entry, as follows: X.nf X 1 = Old style, no compression X 2 = New style, no compression X 3 = Compression of repeated characters only X 4 = Compression of repeated characters plus Huffman SQueezing X 5 = Lempel-Zev packing of repeated strings (old style) X 6 = Lempel-Zev packing of repeated strings (new style) X 7 = Lempel-Zev Williams packing with improved hash function X 8 = Dynamic Lempel-Zev packing with adaptive reset X 9 = Squashing X.fi X XType 5, Lempel-Zev packing, was added as of version 4.0 X XType 6 is Lempel-Zev packing where runs of repeated characters Xhave been collapsed, and was added as of version 4.1 X XType 7 is a variation of Lempel-Zev using a different hash Xfunction which yields speed improvements of 20-25%, and was Xadded as of version 4.6 X XType 8 is a different implementation of Lempel-Zev, using a Xvariable code size and an adaptive block reset, and was added Xas of version 5.0 X XType 9 is another variation of Lempel-Zev, using a larger Xhash table. This method was developed by Phil Katz, and is Xnot supported by the "official" \fBARC\fP programs. X X.I Arc Xwill look for environment variables named \fIARCTEMP\fP or X\fITMPDIR\fP, which, if present, indicates the pathname Xwhere temporary files should be created. This is typically Xthe location of a RAMdisk on a microcomputer, "/tmp/" or Xleft unset. X XSee the included documentation file for more details. X.SH HISTORY X\fIArc\fP has been in use in the CP/M and MSDOS world for many years. XThom Henderson developed the original version, but it is important to note that X\fIarc\fP is based on the file compression theories developed by Huffman, Welch, XKnott, Knuth, and many other scientists. This implementation is based on Xversion 5.21 of the MSDOS program. X.SH BUGS X\fIArc\fP behaves just like the PC version of the program; all functions Xof the "usage" display are working. XFull compatibility with PC ARC files is maintained, the price for which is Xthat \fIarc\fP doesn't like long filenames, and can only archive files with Xnames of up to 12 characters. XIt will *sometimes* do The Right Thing with them, but I suggest Xyou put long-winded filenames in a "shar" before X.IR arc ing Xthem. X XThere shouldn't be any problems, (hah!) but if you find any, please Xsend them to me at: X X hyc@umix.cc.umich.edu X {rutgers, uunet}!umix!hyc X X.SH AUTHORS XOriginal MSDOS program by Thom Henderson X.br XCOPYRIGHT(C) 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED X XOriginal Lempel-Zev code derived from compress 4.0. XModified to support Squashing by Dan Lanciani (ddl@harvard.edu) XPorted from MSDOS by Howard Chu (umix!hyc), Xwith help from John Gilmore (hoptoad!gnu), James Turner (daisy!turner) Xand others. SHAR_EOF if test 7232 -ne "`wc -c < 'Arc.1'`" then echo shar: "error transmitting 'Arc.1'" '(should have been 7232 characters)' fi fi echo shar: "extracting 'Arcinfo'" '(5577 characters)' if test -f 'Arcinfo' then echo shar: "will not over-write existing file 'Arcinfo'" else sed 's/^X//' << \SHAR_EOF > 'Arcinfo' X XARC-FILE.INF, created by Keith Petersen, W8SDZ, 21-Sep-86, extracted Xfrom UNARC.INF by Robert A. Freed. X XFrom: Robert A. Freed XSubject: Technical Information for ARC files XDate: June 24, 1986 X XNote: In the following discussion, UNARC refers to my CP/M-80 program Xfor extracting files from MSDOS ARCs. The definitions of the ARC file Xformat are based on MSDOS ARC512.EXE. X XARCHIVE FILE FORMAT X------------------- X XComponent files are stored sequentially within an archive. Each entry Xis preceded by a 29-byte header, which contains the directory Xinformation. There is no wasted space between entries. (This is in Xcontrast to the centralized directory used by Novosielski libraries. XAlthough random access to subfiles within an archive can be noticeably Xslower than with libraries, archives do have the advantage of not Xrequiring pre-allocation of directory space.) X XArchive entries are normally maintained in sorted name order. The Xformat of the 29-byte archive header is as follows: X XByte 1: 1A Hex. X This marks the start of an archive header. If this byte is not found X when expected, UNARC will scan forward in the file (up to 64K bytes) X in an attempt to find it (followed by a valid compression version). X If a valid header is found in this manner, a warning message is X issued and archive file processing continues. Otherwise, the file is X assumed to be an invalid archive and processing is aborted. (This is X compatible with MS-DOS ARC version 5.12). Note that a special X exception is made at the beginning of an archive file, to accomodate X "self-unpacking" archives (see below). X XByte 2: Compression version, as follows: X X 0 = end of file marker (remaining bytes not present) X 1 = unpacked (obsolete) X 2 = unpacked X 3 = packed X 4 = squeezed (after packing) X 5 = crunched (obsolete) X 6 = crunched (after packing) (obsolete) X 7 = crunched (after packing, using faster hash algorithm) (obsolete) X 8 = crunched (after packing, using dynamic LZW variations) X XBytes 3-15: ASCII file name, nul-terminated. X X(All of the following numeric values are stored low-byte first.) X XBytes 16-19: Compressed file size in bytes. X XBytes 20-21: File date, in 16-bit MS-DOS format: X Bits 15:9 = year - 1980 X Bits 8:5 = month of year X Bits 4:0 = day of month X (All zero means no date.) X XBytes 22-23: File time, in 16-bit MS-DOS format: X Bits 15:11 = hour (24-hour clock) X Bits 10:5 = minute X Bits 4:0 = second/2 (not displayed by UNARC) X XBytes 24-25: Cyclic redundancy check (CRC) value (see below). X XBytes 26-29: Original (uncompressed) file length in bytes. X (This field is not present for version 1 entries, byte 2 = 1. X I.e., in this case the header is only 25 bytes long. Because X version 1 files are uncompressed, the value normally found in X this field may be obtained from bytes 16-19.) X X XSELF-UNPACKING ARCHIVES X----------------------- X XA "self-unpacking" archive is one which can be renamed to a .COM file Xand executed as a program. An example of such a file is the MS-DOS Xprogram ARC512.COM, which is a standard archive file preceded by a Xthree-byte jump instruction. The first entry in this file is a simple X"bootstrap" program in uncompressed form, which loads the subfile XARC.EXE (also uncompressed) into memory and passes control to it. In Xanticipation of a similar scheme for future distribution of UNARC, the Xprogram permits up to three bytes to precede the first header in an Xarchive file (with no error message). X X XCRC COMPUTATION X--------------- X XArchive files use a 16-bit cyclic redundancy check (CRC) for error Xcontrol. The particular CRC polynomial used is x^16 + x^15 + x^2 + 1, Xwhich is commonly known as "CRC-16" and is used in many data Xtransmission protocols (e.g. DEC DDCMP and IBM BSC), as well as by Xmost floppy disk controllers. Note that this differs from the CCITT Xpolynomial (x^16 + x^12 + x^5 + 1), which is used by the XMODEM-CRC Xprotocol and the public domain CHEK program (although these do not Xadhere strictly to the CCITT standard). The MS-DOS ARC program does Xperform a mathematically sound and accurate CRC calculation. (We Xmention this because it contrasts with some unfortunately popular Xpublic domain programs we have witnessed, which from time immemorial Xhave based their calculation on an obscure magazine article which Xcontained a typographical error!) X XAdditional note (while we are on the subject of CRC's): The validity Xof using a 16-bit CRC for checking an entire file is somewhat Xquestionable. Many people quote the statistics related to these Xfunctions (e.g. "all two-bit errors, all single burst errors of 16 or Xfewer bits, 99.997% of all single 17-bit burst errors, etc."), without Xrealizing that these claims are valid only if the total number of bits Xchecked is less than 32767 (which is why they are used in small-packet Xdata transmission protocols). I.e., for file sizes in excess of about X4K bytes, a 16-bit CRC is not really as good as what is often claimed. XThis is not to say that it is bad, but there are more reliable methods Xavailable (e.g. the 32-bit AUTODIN-II polynomial). (End of lecture!) X X Bob Freed X 62 Miller Road X Newton Centre, MA 02159 X Telephone (617) 332-3533 X X SHAR_EOF if test 5577 -ne "`wc -c < 'Arcinfo'`" then echo shar: "error transmitting 'Arcinfo'" '(should have been 5577 characters)' fi fi echo shar: "extracting 'Changes.521'" '(1892 characters)' if test -f 'Changes.521' then echo shar: "will not over-write existing file 'Changes.521'" else sed 's/^X//' << \SHAR_EOF > 'Changes.521' X CHANGES IN VERSION 5.21 X X XThe following changes have been made in ARC version 5.21, but have not Xyet been included in the manual: X Xo When adding files to an archive, ARC now shows the stowage facter X achieved on each file. X Xo A bug was found that would keep an archive entry from being X encrypted if it was stored without compression. This has now been X fixed. X Xo If changes are made to a corrupted archive, the corrupted entries X are discarded. This makes it possible to lose data accidentally. X ARC will now only make changes to a corrupted archive if the W X (suppress Warnings) option has been given. X Xo The N (suppress Notes) option now suppresses the "Creating X archive" note when a new archive is being created. X Xo The N (suppress Notes) option formerly did nothing useful when X used with the L (List files) command. It now causes a terse X listing of filenames only, suitable for use with pipes and X redirection. X Xo The list of filenames given to ARC may now include indirect X references. If a filename begins with an "at sign" ("@"), it is X taken to be the name of a file which contains a list of file X names. The list of file names may include further indirection. X If no extension is given, ".CMD" is assumed. For example, the X command: X X arc a waste junk.txt @trash X X would cause ARC to add JUNK.TXT plus all files listed in the file X TRASH.CMD to an archive named WASTE.ARC. If no file is specified, X then the list is read from standard input. For example, the X command: X X arc ln waste | arc a trash @ X X would cause ARC to add files to TRASH.ARC based on the names of X the files stored in WASTE.ARC. It is probably a good idea to give X the O (Overwrite) option if you are extracting files this way. X X Version 5.21 of MARC also allows for indirection. SHAR_EOF if test 1892 -ne "`wc -c < 'Changes.521'`" then echo shar: "error transmitting 'Changes.521'" '(should have been 1892 characters)' fi fi echo shar: "extracting 'Makefile'" '(4440 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# X# Makefile for Arc v5.21 X# X# Originals from Dan Lanciani, James Turner, and others... X# X# Modified to support squashing, also added targets for the time routine X# library. -- Howard Chu, hyc@umix.cc.umich.edu, 4-11-88 X# X# Modified again by John Gilmore & Howard Chu, July 1988. X# X# I put SRCDIR on a real disk on the ST, but copy the makefile to a X# RAMdisk and compile from there. Makes things go a bit quicker... X# This has to be done in the shell, to get the trailing backslash X# specified correctly. e.g., setenv SRCDIR='d:\src\arc\' XSRCDIR = X XHEADER = $(SRCDIR)arc.h $(SRCDIR)arcs.h X X# Add a ".TTP" suffix to the executable files on an ST. X#PROG = .ttp XPROG = X X# SYSTEM defines your operating system: X# MSDOS for IBM PCs or other MSDOS machines X# GEMDOS for Atari ST (Predefined by MWC, so you don't need to define it.) X# BSD for Berkeley Unix X# SYSV for AT&T System V Unix X# (MTS for Michigan Terminal System, which requires a different makefile) X# (MTS also requires one of USEGFINFO or USECATSCAN for directory search) XSYSTEM = -DSYSV=1 X X# For MWC 3.0 on the Atari ST, use: X#CFLAGS = -VCOMPAC -VPEEP XCFLAGS = -O $(SYSTEM) -Dabort=xabort -Dgetch=xgetch -DLOCAL XLDFLAGS = -s XSHAREDLIB = /lib/crt0s.o /lib/shlib.ifile X X# GNU's gcc is very nice, if you've got it. Otherwise just cc. XCC = cc X X# tmclock is only needed on Unix systems... XTMCLOCK = tmclock.o X X# Files needed for System V XSYSVOBJ = getwd.o rename.o scandir.o utimes.o X#SYSVOBJ = X XOBJS = arc.o arcadd.o arccode.o arccvt.o arcdata.o arcdel.o arcdos.o \ Xarcext.o arcio.o arclst.o arclzw.o arcmatch.o arcpack.o arcrun.o \ Xarcsq.o arcsqs.o arcsvc.o arctst.o arcunp.o arcusq.o arcmisc.o $(SYSVOBJ) X XMOBJ = marc.o arcdata.o arcdos.o arcio.o arcmatch.o arcmisc.o $(SYSVOBJ) X Xall: arc$(PROG) $(PROG)marc X Xarc$(PROG): $(OBJS) $(TMCLOCK) X# $(CC) $(LDFLAGS) -o arc$(PROG) $(OBJS) $(TMCLOCK) X $(LD) $(LDFLAGS) -o arc$(PROG) $(OBJS) $(TMCLOCK) $(SHAREDLIB) X Xmarc$(PROG): $(MOBJ) $(TMCLOCK) X# $(CC) $(LDFLAGS) -o marc$(PROG) $(MOBJ) $(TMCLOCK) X $(LD) $(LDFLAGS) -o marc$(PROG) $(MOBJ) $(TMCLOCK) $(SHAREDLIB) X Xclean: X -rm *.o arc$(PROG) marc$(PROG) X Xshar: X shar -a Arc521.doc > arc_sh.1 X shar -a Arc.1 Arcinfo Changes.521 Makefile Manifest README \ X Read.me Readme.local Readme.too arc.c arc.h > arc_sh.2 X shar -a arcadd.c arccode.c arccvt.c arcdata.c arcdel.c arcdos.c \ X arcext.c arcio.c arclst.c > arc_sh.3 X shar -a arclzw.c arcmatch.c arcmisc.c arcpack.c arcrun.c arcs.h \ X > arc_sh.4 X shar -a arcsq.c arcsqs.c arcsvc.c arctst.c arcunp.c arcusq.c \ X getwd.c > arc_sh.5 X shar -a marc.c memset.c rename.c scandir.3 scandir.c tmclock.c \ X utimes.c > arc_sh.6 X Xarc.o: $(SRCDIR)arc.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arc.c Xmarc.o: $(SRCDIR)marc.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)marc.c Xarcadd.o: $(SRCDIR)arcadd.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcadd.c Xarccode.o: $(SRCDIR)arccode.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arccode.c Xarccvt.o: $(SRCDIR)arccvt.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arccvt.c Xarcdata.o: $(SRCDIR)arcdata.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcdata.c Xarcdel.o: $(SRCDIR)arcdel.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcdel.c Xarcdir.o: $(SRCDIR)arcdir.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcdir.c Xarcdos.o: $(SRCDIR)arcdos.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcdos.c Xarcext.o: $(SRCDIR)arcext.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcext.c Xarcio.o: $(SRCDIR)arcio.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcio.c Xarclst.o: $(SRCDIR)arclst.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arclst.c Xarclzw.o: $(SRCDIR)arclzw.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arclzw.c Xarcmatch.o: $(SRCDIR)arcmatch.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcmatch.c Xarcmisc.o: $(SRCDIR)arcmisc.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcmisc.c Xarcpack.o: $(SRCDIR)arcpack.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcpack.c Xarcrun.o: $(SRCDIR)arcrun.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcrun.c Xarcsq.o: $(SRCDIR)arcsq.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcsq.c Xarcsqs.o: $(SRCDIR)arcsqs.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcsqs.c Xarcsvc.o: $(SRCDIR)arcsvc.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcsvc.c Xarctst.o: $(SRCDIR)arctst.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arctst.c Xarcunp.o: $(SRCDIR)arcunp.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcunp.c Xarcusq.o: $(SRCDIR)arcusq.c $(HEADER) X $(CC) $(CFLAGS) -c $(SRCDIR)arcusq.c X Xtmclock.o: $(SRCDIR)tmclock.c X $(CC) $(CFLAGS) -c $(SRCDIR)tmclock.c SHAR_EOF if test 4440 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 4440 characters)' fi fi echo shar: "extracting 'Manifest'" '(2413 characters)' if test -f 'Manifest' then echo shar: "will not over-write existing file 'Manifest'" else sed 's/^X//' << \SHAR_EOF > 'Manifest' XContents of this distribution.... X 5577 Apr 11 19:15 Arcinfo Description of .ARC file format X 54144 Jun 13 05:26 Arc521.doc Full program documentation, no CRs. X 1892 May 14 1987 Changes.521 Differences between 5.20 and 5.21 X 1323 Apr 11 19:10 Make.tws Makefile for the time routine library X 1731 Jun 13 03:58 Makefile Makefile for ARC X 2413 Jun 13 05:29 Manifest This file X 2269 Jun 18 03:39 Read.me Spiel X 2190 Jun 13 04:23 Readme.too More spiel X 18327 Jun 13 04:09 Sysvarcstuf Useful for Sys V users. X 7232 Jun 12 19:31 arc.1 A man page, *roff source X 11116 Jun 13 04:27 arc.c Main routine, option parser... X 3318 Jun 1 19:59 arc.h System dependencies, externs X 9286 Jun 13 00:31 arcadd.c Top level routine for adding to archive X 1204 Jun 1 15:16 arccode.c Code for file encryption/decryption X 3396 Jun 1 19:18 arccvt.c Convert to new packing method X 2070 Jun 13 04:26 arcdata.c Declarations of externs from arc.h X 2055 Apr 19 01:39 arcdel.c Delete files from archive X 4970 Jun 13 00:41 arcdos.c OS specific file management routines X 4897 Jun 1 20:18 arcext.c Top level routine for extraction X 7384 Jun 2 16:27 arcio.c OS specific low-level I/O routines X 4418 Jun 1 18:06 arclst.c List contents of archive X 22109 Jun 1 20:01 arclzw.c Low-level Lempel-Zev compression X 3026 Jun 1 19:41 arcmatch.c Pattern matching routines X 8319 Jun 13 04:07 arcmisc.c OS specific miscellaneous functions X 7376 Jun 2 16:27 arcpack.c Mid-level compression code X 3838 Jun 1 19:57 arcrun.c Run files from archive X 1645 Apr 17 18:53 arcs.h Declaration of .ARC header format X 14613 Jun 2 16:27 arcsq.c Low-level Huffman Squeeze code X 11587 Jun 1 20:02 arcsqs.c Low-level Squash code X 4680 Jun 13 00:43 arcsvc.c .ARC file utilities X 1284 Apr 19 01:40 arctst.c Test archive integrity X 5325 Jun 7 03:16 arcunp.c Mid-level extraction code X 2484 Jun 2 16:28 arcusq.c Low-level Huffman unSqueezer X 9035 Apr 11 19:10 dtime.c sources for the time routine library... X 7327 Apr 11 19:11 dtimep.lex X 356 Apr 11 19:12 lexedit.sed X 3765 Apr 11 19:12 lexstring.c X 2241 Apr 11 19:13 libtws.3 man page for the time routine library X 9053 Jun 6 01:04 marc.c source for the marc program X 2993 Jun 2 00:38 tws.h header file for the time routine library SHAR_EOF if test 2413 -ne "`wc -c < 'Manifest'`" then echo shar: "error transmitting 'Manifest'" '(should have been 2413 characters)' fi fi echo shar: "extracting 'README'" '(539 characters)' if test -f 'README' then echo shar: "will not over-write existing file 'README'" else sed 's/^X//' << \SHAR_EOF > 'README' XThe enclosed files should be sufficient for bringing up ARC on a Sys V R3 Xsystem. As Jon mentions, Doug Gwyn's directory routines are needed for XSys V R2. The enclosed copy of scandir is new, as far as I can tell, and XI've removed the (unneeded) ftw.? files. Also added a rename() routine, Xcourtesy of Janet Walz. (And an addition from Rich Salz.) X X[see comp.sources.unix, volume 9, for gwyn-dir-lib...] X XThanks again to Jon Zeeff, Janet Walz, and Rich Salz for their help. X -- Howard Chu X hyc@umix.cc.umich.edu X {uunet,rutgers}!umix!hyc SHAR_EOF if test 539 -ne "`wc -c < 'README'`" then echo shar: "error transmitting 'README'" '(should have been 539 characters)' fi fi echo shar: "extracting 'Read.me'" '(2269 characters)' if test -f 'Read.me' then echo shar: "will not over-write existing file 'Read.me'" else sed 's/^X//' << \SHAR_EOF > 'Read.me' XHello again, X herein you should be pleased to find the complete sources for the Xlatest and greatest version of ARC, based on the sources for version 5.21 Xof the MSDOS ARC program. The patches to the previous release, 5.12, with Xsquashing algorithm, have also been applied here. The code is known to Xwork on a Sun 3 running SunOS 3.4, Apollo DN3000 running SR9.7 DOMAIN/IX, XVax 750 running 4.3BSD, and IBM 3090 running MTS. It is also now working Xon Atari STs, as well as Apollo DN3000 running SR10 DOMAIN/OS (Beta). X X Also included is a detailed description of the format of a .ARC Xfile directory entry, in the file named Arcinfo. Could be useful if you're Xtrying to port ARC to any more esoteric systems... X X Jon Zeeff has sent along some code he used to get this working on XSys V style machines. Looks like scandir is all that's really missing. I Xhaven't tried any of it out for myself yet, but the code is in the file X"Sysvarcstuf" should you need it. X X One final necessary inclusion: sources for libtws.a, which was Xposted a long time ago to mod.sources as part of a package he called X"phoon" - a program that calculated and displayed the PHase of the mOON. XThe only thing I use the time routines for here is to convert an expanded Xdate/time back into a Unix style time value, for keeping file modification Xtimes straight. X X Thanks to Leo Wilson (leo@cs.buffalo.edu) for sending his copy of Xa man page for ARC. I've updated it for this version, and included it here Xas well. X X The default value of the (I)mage mode flag has changed. ARC will Xnow treat files as binary files, unless the 'i' flag is given. Handling of XCarriage Returns has been improved a bit. ARC is now a little smarter about Xtemporary files as well. X XTo compile all this stuff... Edit Make.tws (shouldn't need to change anything Xhere, really.) Edit arc.h. After that, just type make and wait a while... X(Oh yeah - there's a few makefile macros that need redefining for Atari ST...) XOk... Well, I've had this for a while, and it works for me, but if somehow XI've goofed, let me know. X X / X /_ , ,_. Howard Chu X/ /(_/(__ University of Michigan X / Computing Center College of LS&A X ' Unix Project Information Systems SHAR_EOF if test 2269 -ne "`wc -c < 'Read.me'`" then echo shar: "error transmitting 'Read.me'" '(should have been 2269 characters)' fi fi echo shar: "extracting 'Readme.local'" '(777 characters)' if test -f 'Readme.local' then echo shar: "will not over-write existing file 'Readme.local'" else sed 's/^X//' << \SHAR_EOF > 'Readme.local' X XThis distribution of Arc v5.21 was derived almost entirely from work by XHoward Chu (uunet!umix!hyc). X XWith the use of the preprocessor definition LOCAL, you can include my Xlocal enhancements and changes. The following changes were made: X X 1) By default, Unix file names are changed to meet MSDOS X file name restrictions when added to an archive. Also, X file names are folded to lowercase when extracted. This X feature can be disabled by the use of the -z option. X X 2) Duplicate file names no longer cause a fatal error, the X second file name is mearly skipped. X XEmmet P. Gray US Army, HQ III Corps & Fort Hood X...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X Directorate of Engineering & Housing X Environmental Management Office X Fort Hood, TX 76544-5057 SHAR_EOF if test 777 -ne "`wc -c < 'Readme.local'`" then echo shar: "error transmitting 'Readme.local'" '(should have been 777 characters)' fi fi echo shar: "extracting 'Readme.too'" '(4064 characters)' if test -f 'Readme.too' then echo shar: "will not over-write existing file 'Readme.too'" else sed 's/^X//' << \SHAR_EOF > 'Readme.too' XNotes for ARC 5.21 June 6, 1988 X XThis program is based on the MSDOS ARC program, version 5.21, plus Xa few enhancements... X X o ARC also performs Huffman Squeezing on data. The Huffman Squeeze X algorithm was removed from MSDOS ARC after version 5.12. It turns X out to be more efficient than Lempel-Ziv style compression when X compressing graphic images. Squeeze analysis is always done now, X and the best of packing, squeezing, or crunching is used. X X o Compresses and extracts Squashed files. "Squashing" was created X by Phil Katz in his PKxxx series of ARC utility programs for X MSDOS. Dan Lanciani wrote the original modifications to ARC's X Crunch code to handle Squashing. I've made minor changes since X then, mostly to reduce the amount of memory required. The 'q' X option flag must be specified to Squash files. The Squashing X algorithm will be used instead of the usual Crunch algorithm, X and will be compared against packing and squeezing, as before. X XSystem specific notes: X X On MTS, an additional option flag, 'i' for "image mode," was Xused. ARC assumes files are text, by default, and will translate XMTS files from EBCDIC to ASCII before storing in an archive, and Xtranslates from ASCII to EBCDIC upon extraction. Specifying the X'i' flag will inhibit this translation. This would most commonly Xbe used when shipping binary images such as TeX DVI files, other X.ARC files stored within an archive, etc... The 'r' (run) command Xis omitted. It just doesn't seem very useful. Also, ARC cannot Xrestore MTS files with their original time stamps. (Maybe in a Xfuture release...) X X On Unix(tm) systems, the 'i' flag is also present. Unix ARC Xassumes a binary file, by default. Here the only translation Xinvolved is in end-of-line processing. When storing text files, ARC will Xchange '\n' to '\r\n', and does the opposite when extracting files. XCarriage returns in any other location are preserved when extracting. XThis translation only occurs if the 'i' flag is given. X X On the Atari ST, the 'h' (for "hold screen") option is present, Xwhich simply delays exiting the program. This is typically used when Xexecuting ARC from the desktop, to allow reading all of ARC's output Xbefore the screen is cleared and the desktop is redrawn. The program Xwill prompt and wait for a keypress before exiting. Note that since Xthere are no "options" for the MARC program, the "hold screen" option Xis always active for MARC. X X On both Unix and Atari systems, ARC & MARC will search for an Xenvironment variable named "ARCTEMP" or "TMPDIR." If present, any Xtemporary files will be created in the specified directory. This is Xprobably insignificant for Unix users, but can be handy on the Atari, Xin combination with a RAMdisk. Highly recommended for floppy users. X(Unfortunately, you can only take advantage of this when running some Xform of command shell that allows setting environment variables. Thus, Xyou won't see any speed gains when running from the desktop.) X X XThat about covers things. The enclosed documentation is taken directly Xfrom the MSDOS distribution of ARC. Unless specified differently here, Xthe programs behave indentically. Note that ARC521.DOC is identical to XARC520.DOC - the differences between the two versions are described in Xthe file CHANGES.521. X XOh yeah - this program may be distributed freely so long as you don't Xmodify it in any way. You may not charge for distributing it. (Don't Xfeel bad, I can't charge for it either. }-) It'd be nice if you kept Xthis and the other enclosed doc files with it when distributing, but XI'm not going to make a fuss about it. Most people are so familiar Xwith the program by now that it wouldn't matter much anyway. You Xshould keep this README file around, so bug reports & such will find Xtheir way back to me. (Bugs? What bugs? Nah, there aren't any bugs...) X X / Howard Chu X ___ /_ , ,_. University of Michigan X / /(_/(__ hyc@umix.cc.umich.edu X / umix!hyc X ' SHAR_EOF if test 4064 -ne "`wc -c < 'Readme.too'`" then echo shar: "error transmitting 'Readme.too'" '(should have been 4064 characters)' fi fi echo shar: "extracting 'arc.c'" '(12303 characters)' if test -f 'arc.c' then echo shar: "will not over-write existing file 'arc.c'" else sed 's/^X//' << \SHAR_EOF > 'arc.c' X/* X * $Header: arc.c,v 1.13 88/11/01 02:22:23 hyc Exp $ X */ X X/* ARC - Archive utility X X Version 5.21, created on 04/22/87 at 15:05:21 X X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This program is a general archive utility, and is used to maintain X an archive of files. An "archive" is a single file that combines X many files, reducing storage space and allowing multiple files to X be handled as one. X X Instructions: X Run this program with no arguments for complete instructions. X X Programming notes: X ARC Version 2 differs from version 1 in that archive entries X are automatically compressed when they are added to the archive, X making a separate compression step unecessary. The nature of the X compression is indicated by the header version number placed in X each archive entry, as follows: X X 1 = Old style, no compression X 2 = New style, no compression X 3 = Compression of repeated characters only X 4 = Compression of repeated characters plus Huffman SQueezing X 5 = Lempel-Zev packing of repeated strings (old style) X 6 = Lempel-Zev packing of repeated strings (new style) X 7 = Lempel-Zev Williams packing with improved hash function X 8 = Dynamic Lempel-Zev packing with adaptive reset X 9 = Dynamic Lempel-Zev packing, larger hash table X X Type 5, Lempel-Zev packing, was added as of version 4.0 X X Type 6 is Lempel-Zev packing where runs of repeated characters X have been collapsed, and was added as of version 4.1 X X Type 7 is a variation of Lempel-Zev using a different hash X function which yields speed improvements of 20-25%, and was X added as of version 4.6 X X Type 8 is a different implementation of Lempel-Zev, using a X variable code size and an adaptive block reset, and was added X as of version 5.0 X X Type 9 is a slight modification of type 8, first used by Phil X Katz in his PKARC utilites. The primary difference is the use X of a hash table twice as large as for type 8, and that this X algorithm called Squashing, doesn't perform run-length encoding X on the input data. X X Verion 4.3 introduced a temporary file for holding the result X of the first crunch pass, thus speeding up crunching. X X Version 4.4 introduced the ARCTEMP environment string, so that X the temporary crunch file may be placed on a ramdisk. Also X added was the distinction bewteen Adding a file in all cases, X and Updating a file only if the disk file is newer than the X corresponding archive entry. X X The compression method to use is determined when the file is X added, based on whichever method yields the smallest result. X X Language: X Computer Innovations Optimizing C86 X*/ X#include <stdio.h> X#include "arc.h" X X#if UNIX X#include <sys/types.h> X#include <sys/stat.h> X#endif X X#ifdef LOCAL Xint unix_names = 0; X#endif /* LOCAL */ X Xint strlen(); Xvoid addarc(), delarc(), extarc(), lstarc(), tstarc(), cvtarc(), runarc(); Xvoid abort(); Xstatic void expandlst(); X#if MTS Xvoid etoa(); X#endif X#if GEMDOS Xlong _stksize = 65536L; X#endif Xchar *strcpy(), *strcat(); Xchar *makefnam(); /* filename fixup routine */ X Xstatic char **lst; /* files list */ Xstatic int lnum; /* length of files list */ X Xmain(num, arg) /* system entry point */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ X{ X char opt = 0;/* selected action */ X char *a; /* option pointer */ X void upper();/* case conversion routine */ X char *index();/* string index utility */ X char *envfind(); /* environment searcher */ X int n; /* index */ X char *arctemp2, *calloc(), *mktemp(); X#if GEMDOS X void exitpause(); X int append; X#endif X#if MTS X fortran void guinfo(); X char gotinf[4]; X#endif X#if UNIX X struct stat sbuf; X#endif X X if (num < 3) { X printf("ARC - Archive utility, Version 5.21, created on 04/22/87 at 15:05:21\n"); X/* printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;"); X printf(" ALL RIGHTS RESERVED\n\n"); X printf("Please refer all inquiries to:\n\n"); X printf(" System Enhancement Associates\n"); X printf(" 21 New Street, Wayne NJ 07470\n\n"); X printf("You may copy and distribute this program freely,"); X printf(" provided that:\n"); X printf(" 1) No fee is charged for such copying and"); X printf(" distribution, and\n"); X printf(" 2) It is distributed ONLY in its original,"); X printf(" unmodified state.\n\n"); X printf("If you like this program, and find it of use, then your"); X printf(" contribution will\n"); X printf("be appreciated. You may not use this product in a"); X printf(" commercial environment\n"); X printf("or a governmental organization without paying a license"); X printf(" fee of $35. Site\n"); X printf("licenses and commercial distribution licenses are"); X printf(" available. A program\n"); X printf("disk and printed documentation are available for $50.\n"); X printf("\nIf you fail to abide by the terms of this license, "); X printf(" then your conscience\n"); X printf("will haunt you for the rest of your life.\n\n"); */ X#if MSDOS X printf("Usage: ARC {amufdxerplvtc}[bswnoq][g<password>]"); X#endif X#if GEMDOS X printf("Usage: ARC {amufdxerplvtc}[bhswnoq][g<password>]"); X#endif X#if UNIX X#ifdef LOCAL X printf("Usage: arc {amufdxerplvtc}[biswnoqz][g<password>]"); X#else /* LOCAL */ X printf("Usage: arc {amufdxerplvtc}[biswnoq][g<password>]"); X#endif /* LOCAL */ X#endif X#if MTS X printf("Parameters: {amufdxeplvtc}[biswnoq][g<password>]"); X#endif X printf(" <archive> [<filename> . . .]\n"); X printf("Where: a = add files to archive\n"); X printf(" m = move files to archive\n"); X printf(" u = update files in archive\n"); X printf(" f = freshen files in archive\n"); X printf(" d = delete files from archive\n"); X printf(" x,e = extract files from archive\n"); X#if !MTS X printf(" r = run files from archive\n"); X#endif X printf(" p = copy files from archive to"); X printf(" standard output\n"); X printf(" l = list files in archive\n"); X printf(" v = verbose listing of files in archive\n"); X printf(" t = test archive integrity\n"); X printf(" c = convert entry to new packing method\n"); X printf(" b = retain backup copy of archive\n"); X#if GEMDOS X printf(" h = hold screen after finishing\n"); X#endif X#if MTS X printf(" i = suppress ASCII/EBCDIC translation\n"); X#endif X#if UNIX X printf(" i = suppress image mode (translate EOL)\n"); X#endif X printf(" s = suppress compression (store only)\n"); X printf(" w = suppress warning messages\n"); X printf(" n = suppress notes and comments\n"); X printf(" o = overwrite existing files when"); X printf(" extracting\n"); X printf(" q = squash instead of crunching\n"); X printf(" g = Encrypt/decrypt archive entry\n"); X#ifdef LOCAL X printf(" z = use Unix file names (as much as possible)\n"); X#endif /* LOCAL */ X printf("\nAdapted from MSDOS by Howard Chu\n"); X /* X * printf("\nPlease refer to the program documentation for"); X * printf(" complete instructions.\n"); X */ X#if GEMDOS X exitpause(); X#endif X return 1; X } X /* see where temp files go */ X#if !MTS X arctemp = calloc(1, STRLEN); X if (!(arctemp2 = envfind("ARCTEMP"))) X arctemp2 = envfind("TMPDIR"); X if (arctemp2) { X strcpy(arctemp, arctemp2); X n = strlen(arctemp); X if (arctemp[n - 1] != CUTOFF) X arctemp[n] = CUTOFF; X } X#if UNIX X else strcpy(arctemp, "/tmp/"); X#endif X#if !MSDOS X { X static char tempname[] = "AXXXXXX"; X strcat(arctemp, mktemp(tempname)); X } X#else X strcat(arctemp, "$ARCTEMP"); X arctemp2 = NULL; X#endif X#else X guinfo("SHFSEP ", gotinf); X sepchr[0] = gotinf[0]; X guinfo("SCRFCHAR", gotinf); X tmpchr[0] = gotinf[0]; X arctemp = "-$$$"; X arctemp[0] = tmpchr[0]; X#endif X X#if !UNIX X /* avoid any case problems with arguments */ X X for (n = 1; n < num; n++) /* for each argument */ X upper(arg[n]); /* convert it to uppercase */ X#else X /* avoid case problems with command options */ X upper(arg[1]); /* convert to uppercase */ X#endif X X /* create archive names, supplying defaults */ X#if UNIX X if (!stat(arg[2],&sbuf)) { X if ((sbuf.st_mode & S_IFMT) == S_IFDIR) X makefnam(arg[2],".arc",arcname); X else X strcpy(arcname,arg[2]); X } else X makefnam(arg[2],".arc",arcname); X#else X makefnam(arg[2], ".ARC", arcname); X#endif X /* makefnam(".$$$",arcname,newname); */ X sprintf(newname, "%s.arc", arctemp); X makefnam(".BAK", arcname, bakname); X X /* now scan the command and see what we are to do */ X X for (a = arg[1]; *a; a++) { /* scan the option flags */ X#if !MTS X if (index("AMUFDXEPLVTCR", *a)) { /* if a known command */ X#else X if (index("AMUFDXEPLVTC", *a)) { X#endif X if (opt)/* do we have one yet? */ X abort("Cannot mix %c and %c", opt, *a); X opt = *a; /* else remember it */ X } else if (*a == 'B') /* retain backup copy */ X keepbak = 1; X X else if (*a == 'W') /* suppress warnings */ X warn = 0; X#if !DOS X else if (*a == 'I') /* image mode, no ASCII/EBCDIC x-late */ X image = !image; X#endif X#if GEMDOS X else if (*a == 'H') /* pause before exit */ X hold = 1; X#endif X X else if (*a == 'N') /* suppress notes and comments */ X note = 0; X X else if (*a == 'O') /* overwrite file on extract */ X overlay = 1; X X else if (*a == 'G') { /* garble */ X password = a + 1; X while (*a) X a++; X a--; X#if MTS X etoa(password, strlen(password)); X#endif X } else if (*a == 'S') /* storage kludge */ X nocomp = 1; X X else if (*a == 'K') /* special kludge */ X kludge = 1; X X else if (*a == 'Q') /* use squashing */ X dosquash = 1; X#ifdef LOCAL X else if (*a == 'Z') /* use Unix file names */ X unix_names = 1; X#endif /* LOCAL */ X X else if (*a == '-' || *a == '/') /* UNIX and PC-DOS X * option markers */ X ; X X else X abort("%c is an unknown command", *a); X } X X if (!opt) X abort("I have nothing to do!"); X X /* get the files list set up */ X X lnum = num - 3; /* initial length of list */ X lst = (char **) calloc((lnum==0) ? 1:lnum, X sizeof(char *)); /* initial list */ X for (n = 3; n < num; n++) X lst[n - 3] = arg[n]; X X for (n = 0; n < lnum;) {/* expand indirect references */ X if (*lst[n] == '@') X expandlst(n); X#if GEMDOS X /* redirect stdout from the desktop...*/ X else if (*lst[n] == '>') { X arctemp2 = (++lst[n]); X lst[n] = lst[lnum-1]; /* delete this entry */ X lnum--; X if (arctemp2[0] == '>') { X append = 1; X arctemp2++; X } X else append = 0; X } X#endif X else X n++; X } X#if GEMDOS X if (arctemp2) X freopen(arctemp2,append ? "a" : "w",stdout); X#endif X X /* act on whatever action command was given */ X X switch (opt) { /* action depends on command */ X case 'A': /* Add */ X case 'M': /* Move */ X case 'U': /* Update */ X case 'F': /* Freshen */ X addarc(lnum, lst, (opt == 'M'), (opt == 'U'), (opt == 'F')); X break; X X case 'D': /* Delete */ X delarc(lnum, lst); X break; X X case 'E': /* Extract */ X case 'X': /* eXtract */ X case 'P': /* Print */ X extarc(lnum, lst, (opt == 'P')); X break; X X case 'V': /* Verbose list */ X bose = 1; X case 'L': /* List */ X lstarc(lnum, lst); X break; X X case 'T': /* Test */ X tstarc(); X break; X X case 'C': /* Convert */ X cvtarc(lnum, lst); X break; X#if !MTS X case 'R': /* Run */ X runarc(lnum, lst); X break; X#endif X default: X abort("I don't know how to do %c yet!", opt); X } X#if GEMDOS X if (hold) X exitpause(); X#endif X return nerrs; X} Xstatic void Xexpandlst(n) /* expand an indirect reference */ X int n; /* number of entry to expand */ X{ X FILE *lf, *fopen(); /* list file, opener */ X char *malloc(), *realloc(); /* memory managers */ X char buf[100]; /* input buffer */ X int x; /* index */ X char *p = lst[n] + 1; /* filename pointer */ X X if (*p) { /* use name if one was given */ X makefnam(p, ".CMD", buf); X if (!(lf = fopen(buf, "r"))) X abort("Cannot read list of files in %s", buf); X } else X lf = stdin; /* else use standard input */ X X for (x = n + 1; x < lnum; x++) /* drop reference from the list */ X lst[x - 1] = lst[x]; X lnum--; X X while (fscanf(lf, "%99s", buf) > 0) { /* read in the list */ X if (!(lst =(char **)realloc(lst, (lnum + 1) * sizeof(char *)))) X abort("too many file references"); X X lst[lnum] = malloc(strlen(buf) + 1); X strcpy(lst[lnum], buf); /* save the name */ X lnum++; X } X X if (lf != stdin) /* avoid closing standard input */ X fclose(lf); X} SHAR_EOF if test 12303 -ne "`wc -c < 'arc.c'`" then echo shar: "error transmitting 'arc.c'" '(should have been 12303 characters)' fi fi echo shar: "extracting 'arc.h'" '(2930 characters)' if test -f 'arc.h' then echo shar: "will not over-write existing file 'arc.h'" else sed 's/^X//' << \SHAR_EOF > 'arc.h' X/* X * $Header: arc.h,v 1.10 88/08/01 14:28:29 hyc Exp $ X */ X X#undef DOS /* Just in case... */ X#undef UNIX X X/* X * Assumptions: X * char = 8 bits X * short = 16 bits X * long = 32 bits X * int >= 16 bits X */ X X#if MSDOS || GEMDOS X#define DOS 1 X#define CUTOFF '\\' X#define OPEN_R "rb" X#define OPEN_W "wb" X#endif X X#if !MSDOS X#define envfind getenv X#define setmem(a, b, c) memset(a, c, b) X#endif X X#if BSD || SYSV X#define UNIX 1 X#define CUTOFF '/' X#define OPEN_R "r" X#define OPEN_W "w" X#include <ctype.h> X#endif X X#if MTS X#define CUTOFF sepchr[0] X#endif X X#if MTS || SYSV X#define rindex strrchr X#define index strchr X#endif X X/* ARC - Archive utility - ARC Header X X Version 2.17, created on 04/22/87 at 13:09:43 X X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This is the header file for the ARC archive utility. It defines X global parameters and the references to the external data. X X X Language: X Computer Innovations Optimizing C86 X*/ X X#define ARCMARK 26 /* special archive marker */ X#define ARCVER 9 /* archive header version code */ X#define STRLEN 100 /* system standard string length */ X#define FNLEN 13 /* file name length */ X#define MAXARG 400 /* maximum number of arguments */ X X#ifndef DONT_DEFINE /* Defined by arcdata.c */ X#include "arcs.h" X Xextern int keepbak; /* true if saving the old archive */ X#if !DOS Xextern int image; /* true to suppress CRLF/LF x-late */ X#endif X#if MTS Xextern char sepchr[2]; /* Shared file separator, default = ':' */ Xextern char tmpchr[2]; /* Temporary file prefix, default = '-' */ X#endif X#if GEMDOS Xextern int hold; /* hold screen before exiting */ X#endif Xextern int warn; /* true to print warnings */ Xextern int note; /* true to print comments */ Xextern int bose; /* true to be verbose */ Xextern int nocomp; /* true to suppress compression */ Xextern int overlay; /* true to overlay on extract */ Xextern int kludge; /* kludge flag */ Xextern char *arctemp; /* arc temp file prefix */ Xextern char *password; /* encryption password pointer */ Xextern int nerrs; /* number of errors encountered */ Xextern int changing; /* true if archive being modified */ X Xextern char hdrver; /* header version */ X Xextern FILE *arc; /* the old archive */ Xextern FILE *new; /* the new archive */ Xextern char arcname[STRLEN];/* storage for archive name */ Xextern char bakname[STRLEN];/* storage for backup copy name */ Xextern char newname[STRLEN];/* storage for new archive name */ Xextern unsigned short arcdate; /* archive date stamp */ Xextern unsigned short arctime; /* archive time stamp */ Xextern unsigned short olddate; /* old archive date stamp */ Xextern unsigned short oldtime; /* old archive time stamp */ Xextern int dosquash; /* squash instead of crunch */ X#endif /* DONT_DEFINE */ SHAR_EOF if test 2930 -ne "`wc -c < 'arc.h'`" then echo shar: "error transmitting 'arc.h'" '(should have been 2930 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (01/02/89)
This is part 3 (of 6) to the Arc v5.21 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # arcadd.c # arccode.c # arccvt.c # arcdata.c # arcdel.c # arcdos.c # arcext.c # arcio.c # arclst.c # This archive created: Sun Jan 1 12:48:17 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'arcadd.c'" '(12955 characters)' if test -f 'arcadd.c' then echo shar: "will not over-write existing file 'arcadd.c'" else sed 's/^X//' << \SHAR_EOF > 'arcadd.c' X/* X * $Header: arcadd.c,v 1.10 88/11/16 17:43:25 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCADD X * X * Version 3.40, created on 06/18/86 at 13:10:18 X * X * (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to add files to an archive. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X#if MTS X#include <mts.h> X#endif X Xstatic int addfile(); Xchar *strcpy(); Xint strcmp(), strlen(), free(), readhdr(), unlink(); X#if UNIX Xint izadir(); X#endif Xvoid writehdr(), filecopy(), getstamp(); Xvoid pack(), closearc(), openarc(), abort(); X Xvoid Xaddarc(num, arg, move, update, fresh) /* add files to archive */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ Xint move; /* true if moving file */ Xint update; /* true if updating */ Xint fresh; /* true if freshening */ X{ X char *d, *dir(); /* directory junk */ X char buf[STRLEN]; /* pathname buffer */ X char **path; /* pointer to pointers to paths */ X char **name; /* pointer to pointers to names */ X int nfiles = 0; /* number of files in lists */ X int notemp; /* true until a template works */ X int nowork = 1; /* true until files are added */ X char *i, *rindex(); /* string indexing junk */ X char *malloc(), *realloc(); /* memory allocators */ X int n; /* index */ X#ifdef LOCAL X extern int unix_names; X#endif /* LOCAL */ X#if MSDOS X unsigned int coreleft(); /* remaining memory reporter */ X#endif X int addbunch(); X X if (num < 1) { /* if no files named */ X num = 1; /* then fake one */ X#if DOS X arg[0] = "*.*"; /* add everything */ X#endif X#if UNIX X arg[0] = "*"; X#endif X#if MTS X arg[0] = "?"; X#endif X } X path = (char **) malloc(sizeof(char **)); X name = (char **) malloc(sizeof(char **)); X X X for (n = 0; n < num; n++) { /* for each template supplied */ X strcpy(buf, arg[n]); /* get ready to fix path */ X#if !MTS X if (!(i = rindex(buf, '\\'))) X if (!(i = rindex(buf, '/'))) X if (!(i = rindex(buf, ':'))) X i = buf - 1; X#else X if (!(i = rindex(buf, sepchr[0]))) X if (buf[0] != tmpchr[0]) X i = buf - 1; X else X i = buf; X#endif X i++; /* pointer to where name goes */ X X notemp = 1; /* reset files flag */ X for (d = dir(arg[n]); d; d = dir(NULL)) { X notemp = 0; /* template is giving results */ X nfiles++; /* add each matching file */ X path = (char **) realloc(path, nfiles * sizeof(char **)); X name = (char **) realloc(name, nfiles * sizeof(char **)); X strcpy(i, d); /* put name in path */ X path[nfiles - 1] = malloc(strlen(buf) + 1); X strcpy(path[nfiles - 1], buf); X name[nfiles - 1] = d; /* save name */ X#if LOCAL X /* make it a MSDOS file name */ X if (!unix_names) { X if (legalize(path[nfiles-1], name[nfiles-1])) { X nfiles--; X continue; X } X } X#endif /* LOCAL */ X#if MSDOS X if (coreleft() < 5120) { X nfiles = addbunch(nfiles, path, name, move, update, fresh); X nowork = nowork && !nfiles; X while (nfiles) { X free(path[--nfiles]); X free(name[nfiles]); X } X free(path); X free(name); X path = name = NULL; X } X#endif X } X if (notemp && warn) X printf("No files match: %s\n", arg[n]); X } X X if (nfiles) { X nfiles = addbunch(nfiles, path, name, move, update, fresh); X nowork = nowork && !nfiles; X while (nfiles) { X free(path[--nfiles]); X free(name[nfiles]); X } X free(path); X free(name); X } X if (nowork && warn) X printf("No files were added.\n"); X} X Xint Xaddbunch(nfiles, path, name, move, update, fresh) /* add a bunch of files */ X int nfiles; /* number of files to add */ X char **path; /* pointers to pathnames */ X char **name; /* pointers to filenames */ X int move; /* true if moving file */ X int update; /* true if updating */ X int fresh; /* true if freshening */ X{ X int m, n; /* indices */ X char *d; /* swap pointer */ X struct heads hdr; /* file header data storage */ X X for (n = 0; n < nfiles - 1; n++) { /* sort the list of names */ X for (m = n + 1; m < nfiles; m++) { X if (strcmp(name[n], name[m]) > 0) { X d = path[n]; X path[n] = path[m]; X path[m] = d; X d = name[n]; X name[n] = name[m]; X name[m] = d; X } X } X } X X for (n = 0; n < nfiles - 1;) { /* consolidate the list of names */ X if (!strcmp(path[n], path[n + 1]) /* if duplicate names */ X ||!strcmp(path[n], arcname) /* or this archive */ X#if UNIX X ||izadir(path[n]) /* or a directory */ X#endif X ||!strcmp(path[n], newname) /* or the new version */ X ||!strcmp(path[n], bakname)) { /* or its backup */ X free(path[n]); /* then forget the file */ X free(name[n]); X for (m = n; m < nfiles - 1; m++) { X path[m] = path[m + 1]; X name[m] = name[m + 1]; X } X nfiles--; X } else X n++; /* else test the next one */ X } X X if (!strcmp(path[n], arcname) /* special check for last file */ X ||!strcmp(path[n], newname) /* courtesy of Rick Moore */ X#if UNIX X ||izadir(path[n]) X#endif X || !strcmp(path[n], bakname)) { X free(path[n]); X free(name[n]); X nfiles--; X } X if (!nfiles) /* make sure we got some */ X return 0; X X for (n = 0; n < nfiles - 1; n++) { /* watch out for duplicate X * names */ X#ifdef LOCAL X if (!strcmp(name[n], name[n + 1])) { X printf("Duplicate filenames: %s %s\n", path[n], path[n+1]); X printf("Skipping filename: %s\n", path[n+1]); X free(path[n+1]); X free(name[n+1]); X for (m = n+1; m < nfiles-1 ; m++) { X path[m] = path[m+1]; X name[m] = name[m+1]; X } X nfiles--; X } X#else /* LOCAL */ X if (!strcmp(name[n], name[n + 1])) X abort("Duplicate filenames:\n %s\n %s", path[n], path[n + 1]); X#endif /* LOCAL */ X } X openarc(1); /* open archive for changes */ X X for (n = 0; n < nfiles;) { /* add each file in the list */ X if (addfile(path[n], name[n], update, fresh) < 0) { X free(path[n]); /* remove this name if */ X free(name[n]); /* it wasn't added */ X for (m = n; m < nfiles-1 ; m++) { X path[m] = path[m+1]; X name[m] = name[m+1]; X } X nfiles--; X } else n++; X } X X /* now we must copy over all files that follow our additions */ X X while (readhdr(&hdr, arc)) { /* while more entries to copy */ X writehdr(&hdr, new); X filecopy(arc, new, hdr.size); X } X hdrver = 0; /* archive EOF type */ X writehdr(&hdr, new); /* write out our end marker */ X closearc(1); /* close archive after changes */ X X if (move) { /* if this was a move */ X for (n = 0; n < nfiles; n++) { /* then delete each file X * added */ X if (unlink(path[n]) && warn) { X printf("Cannot unsave %s\n", path[n]); X nerrs++; X } X } X } X return nfiles; /* say how many were added */ X} X Xstatic int Xaddfile(path, name, update, fresh) /* add named file to archive */ X char *path; /* path name of file to add */ X char *name; /* name of file to add */ X int update; /* true if updating */ X int fresh; /* true if freshening */ X{ X struct heads nhdr; /* data regarding the new file */ X struct heads ohdr; /* data regarding an old file */ X FILE *f, *fopen(); /* file to add, opener */ X long starts, ftell(); /* file locations */ X int upd = 0;/* true if replacing an entry */ X#ifdef LOCAL X void upper(); X#endif /* LOCAL */ X X#if !MTS X if (!(f = fopen(path, OPEN_R))) X#else X if (image) X f = fopen(path, "rb"); X else X f = fopen(path, "r"); X if (!f) X#endif X { X if (warn) { X printf("Cannot read file: %s\n", path); X nerrs++; X } X return(-1); X } X#if !DOS X if (strlen(name) >= FNLEN) { X if (warn) { X char buf[STRLEN]; X printf("WARNING: File %s name too long!\n", name); X name[FNLEN-1]='\0'; X while(1) { X printf(" Truncate to %s (y/n)? ", name); X fflush(stdout); X fgets(buf, STRLEN, stdin); X *buf = toupper(*buf); X if (*buf == 'Y' || *buf == 'N') X break; X } X if (*buf == 'N') { X printf("Skipping...\n"); X fclose(f); X return(-1); X } X } X else { X if (note) X printf("Skipping file: %s - name too long.\n", X name); X fclose(f); X return(-1); X } X } X#endif X#ifdef LOCAL X upper(name); X#endif /* LCOAL */ X strcpy(nhdr.name, name);/* save name */ X nhdr.size = 0; /* clear out size storage */ X nhdr.crc = 0; /* clear out CRC check storage */ X#if !MTS X getstamp(f, &nhdr.date, &nhdr.time); X#else X { X char *buffer, *malloc(); X int inlen; X struct GDDSECT *region; X X region=gdinfo(f->_fd._fdub); X inlen=region->GDINLEN; X buffer=malloc(inlen); /* maximum line length */ X setbuf(f,buffer); X f->_bufsiz=inlen; X f->_mods|=_NOIC; /* Don't do "$continue with" */ X f->_mods&=~_IC; /* turn it off, if set... */ X } X getstamp(path, &nhdr.date, &nhdr.time); X#endif X X /* position archive to spot for new file */ X X if (arc) { /* if adding to existing archive */ X starts = ftell(arc); /* where are we? */ X while (readhdr(&ohdr, arc)) { /* while more files to check */ X if (!strcmp(ohdr.name, nhdr.name)) { X upd = 1; /* replace existing entry */ X if (update || fresh) { /* if updating or X * freshening */ X if (nhdr.date < ohdr.date X || (nhdr.date == ohdr.date && nhdr.time <= ohdr.time)) { X fseek(arc, starts, 0); X fclose(f); X return(0);/* skip if !newer */ X } X } X } X if (strcmp(ohdr.name, nhdr.name) >= 0) X break; /* found our spot */ X X writehdr(&ohdr, new); /* entry preceeds update; X * keep it */ X filecopy(arc, new, ohdr.size); X starts = ftell(arc); /* now where are we? */ X } X X if (upd) { /* if an update */ X if (note) { X printf("Updating file: %-12s ", name); X fflush(stdout); X } X fseek(arc, ohdr.size, 1); X } else if (fresh) { /* else if freshening */ X fseek(arc, starts, 0); /* then do not add files */ X fclose(f); X return(0); X } else { /* else adding a new file */ X if (note) { X printf("Adding file: %-12s ", name); X fflush(stdout); X } X fseek(arc, starts, 0); /* reset for next time */ X } X } else { /* no existing archive */ X if (fresh) { /* cannot freshen nothing */ X fclose(f); X return(0); X } else if (note) { /* else adding a file */ X printf("Adding file: %-12s ", name); X fflush(stdout); X } X } X X starts = ftell(new); /* note where header goes */ X hdrver = ARCVER; /* anything but end marker */ X writehdr(&nhdr, new); /* write out header skeleton */ X pack(f, new, &nhdr); /* pack file into archive */ X fseek(new, starts, 0); /* move back to header skeleton */ X writehdr(&nhdr, new); /* write out real header */ X fseek(new, nhdr.size, 1); /* skip over data to next header */ X fclose(f); /* all done with the file */ X return(0); X} X X#ifdef LOCAL X/* X * Convert a Unix filename to a legal MSDOS name. Returns a 1 if the file X * can't be found (or is not a regular file). Will truncate file and X * extension names, will substitute the letter 'X' for any illegal character X * in the name. X */ X X#include <ctype.h> X#include <sys/types.h> X#include <sys/stat.h> X Xint Xlegalize(path, name) Xchar *path, *name; X{ X static char *dev[8] = {"CON", "AUX", "COM1", "LPT1", "PRN", "LPT2", X "LPT3", "NUL"}; X char *s, *temp, *ext, *strcpy(), *strpbrk(), buf[256]; X int i, dot, modified, verbose; X struct stat stbuf; X X/* verbose = warn; */ X verbose = 0; X X if (stat(path, &stbuf) < 0) { X fprintf(stderr, "Can't find \"%s\"\n", path); X return(1); X } X if ((stbuf.st_mode & S_IFREG) != S_IFREG) { X if (verbose) X fprintf(stderr, "\"%s\" Is not a regular file\n", path); X return(1); X } X X strcpy(buf, name); X temp = buf; X X ext = ""; X dot = 0; X for (s = temp; *s; ++s) { X if (*s == '.' && !dot) { X dot = 1; X *s = '\0'; X ext = s + 1; X } X if (islower(*s)) X *s = toupper(*s); X } X if (*temp == '\0') { X temp = "X"; X if (verbose) X printf("\"%s\" Null name component, using \"%s.%s\"\n", name, temp, ext); X } X for (i=0; i<8; i++) { X if (!strcmp(temp, dev[i])) { X *temp = 'X'; X if (verbose) X printf("\"%s\" Is a device name, using \"%s.%s\"\n", name, temp, ext); X } X } X if (strlen(temp) > 8) { X *(temp+8) = '\0'; X if (verbose) X printf("\"%s\" Name too long, using, \"%s.%s\"\n", name, temp, ext); X } X if (strlen(ext) > 3) { X *(ext+3) = '\0'; X if (verbose) X printf("\"%s\" Extension too long, using \"%s.%s\"\n", name, temp, ext); X } X modified = 0; X while (s = strpbrk(temp, "^+=/[]:',?*\\<>|\". ")) { X modified++; X *s = 'X'; X } X while (s = strpbrk(ext, "^+=/[]:',?*\\<>|\". ")) { X modified++; X *s = 'X'; X } X if (modified && verbose) X printf("\"%s\" Contains illegal character(s), using \"%s.%s\"\n", name, temp, ext); X X if (*ext != '\0') X sprintf(name, "%s.%s", temp, ext); X else X strcpy(name, temp); X return(0); X} X X#ifdef BSD X Xchar * Xstrpbrk(p1, p2) Xchar *p1, *p2; X{ X char *p2start = p2; X X while (*p1) { X while (*p2) { X if (*p2 == *p1) X return p1; X p2++; X } X p2 = p2start; X p1++; X } X return NULL; X} X X#endif /* BSD */ X#endif /* LOCAL */ SHAR_EOF if test 12955 -ne "`wc -c < 'arcadd.c'`" then echo shar: "error transmitting 'arcadd.c'" '(should have been 12955 characters)' fi fi echo shar: "extracting 'arccode.c'" '(1192 characters)' if test -f 'arccode.c' then echo shar: "will not over-write existing file 'arccode.c'" else sed 's/^X//' << \SHAR_EOF > 'arccode.c' X/* X * $Header: arccode.c,v 1.1 88/06/01 15:15:58 hyc Locked $ X */ X X/* X * ARC - Archive utility - ARCCODE X * X * Version 1.02, created on 01/20/86 at 13:33:35 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to encrypt and decrypt data X * in an archive. The encryption method is nothing fancy, being just a X * routine XOR, but it is used on the packed data, and uses a variable length X * key. The end result is something that is in theory crackable, but I'd X * hate to try it. It should be more than sufficient for casual use. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X Xstatic char *p; /* password pointer */ X Xvoid Xsetcode() X{ /* get set for encoding/decoding */ X p = password; /* reset password pointer */ X} X Xint Xcode(c) /* encode some character */ Xint c; /* character to encode */ X{ X if (p) { /* if password is in use */ X if (!*p) /* if we reached the end */ X p = password; /* then wrap back to the start */ X return c ^ *p++;/* very simple here */ X } else X return c; /* else no encryption */ X} SHAR_EOF if test 1192 -ne "`wc -c < 'arccode.c'`" then echo shar: "error transmitting 'arccode.c'" '(should have been 1192 characters)' fi fi echo shar: "extracting 'arccvt.c'" '(3396 characters)' if test -f 'arccvt.c' then echo shar: "will not over-write existing file 'arccvt.c'" else sed 's/^X//' << \SHAR_EOF > 'arccvt.c' X/* X * $Header: arccvt.c,v 1.5 88/06/01 19:17:40 hyc Locked $ X */ X X/* X * ARC - Archive utility - ARCCVT X * X * Version 1.16, created on 02/03/86 at 22:53:02 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to convert archives to use X * newer file storage methods. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X Xvoid openarc(), rempath(), closearc(), abort(), pack(), writehdr(), filecopy(); Xint match(), readhdr(), unpack(), unlink(); X Xstatic char tempname[STRLEN]; /* temp file name */ X Xvoid Xcvtarc(num, arg) /* convert archive */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ X{ X struct heads hdr; /* file header */ X int cvt; /* true to convert current file */ X int did[MAXARG];/* true when argument was used */ X int n; /* index */ X char *makefnam(); /* filename fixer */ X FILE *fopen();/* file opener */ X void cvtfile(); X X if (arctemp) /* use temp area if specified */ X sprintf(tempname, "%s.CVT", arctemp); X else X makefnam("$ARCTEMP.CVT", arcname, tempname); X#if !DOS X image = 1; X#endif X X openarc(1); /* open archive for changes */ X X for (n = 0; n < num; n++) /* for each argument */ X did[n] = 0; /* reset usage flag */ X rempath(num, arg); /* strip off paths */ X X if (num) { /* if files were named */ X while (readhdr(&hdr, arc)) { /* while more files to check */ X cvt = 0;/* reset convert flag */ X for (n = 0; n < num; n++) { /* for each template X * given */ X if (match(hdr.name, arg[n])) { X cvt = 1; /* turn on convert flag */ X did[n] = 1; /* turn on usage flag */ X break; /* stop looking */ X } X } X X if (cvt)/* if converting this one */ X cvtfile(&hdr); /* then do it */ X else { /* else just copy it */ X writehdr(&hdr, new); X filecopy(arc, new, hdr.size); X } X } X } else X while (readhdr(&hdr, arc)) /* else convert all files */ X cvtfile(&hdr); X X hdrver = 0; /* archive EOF type */ X writehdr(&hdr, new); /* write out our end marker */ X closearc(1); /* close archive after changes */ X X if (note) { X for (n = 0; n < num; n++) { /* report unused args */ X if (!did[n]) { X printf("File not found: %s\n", arg[n]); X nerrs++; X } X } X } X} X Xvoid Xcvtfile(hdr) /* convert a file */ X struct heads *hdr; /* pointer to header data */ X{ X long starts, ftell(); /* where the file goes */ X FILE *tmp, *fopen(); /* temporary file */ X X if (!(tmp = fopen(tempname, "w+b"))) X abort("Unable to create temporary file %s", tempname); X X if (note) { X printf("Converting file: %-12s reading, ", hdr->name); X fflush(stdout); X } X unpack(arc, tmp, hdr); /* unpack the entry */ X fseek(tmp, 0L, 0); /* reset temp for reading */ X X starts = ftell(new); /* note where header goes */ X hdrver = ARCVER; /* anything but end marker */ X writehdr(hdr, new); /* write out header skeleton */ X pack(tmp, new, hdr); /* pack file into archive */ X fseek(new, starts, 0); /* move back to header skeleton */ X writehdr(hdr, new); /* write out real header */ X fseek(new, hdr->size, 1); /* skip over data to next header */ X fclose(tmp); /* all done with the file */ X if (unlink(tempname) && warn) { X printf("Cannot unsave %s\n", tempname); X nerrs++; X } X} SHAR_EOF if test 3396 -ne "`wc -c < 'arccvt.c'`" then echo shar: "error transmitting 'arccvt.c'" '(should have been 3396 characters)' fi fi echo shar: "extracting 'arcdata.c'" '(2067 characters)' if test -f 'arcdata.c' then echo shar: "will not over-write existing file 'arcdata.c'" else sed 's/^X//' << \SHAR_EOF > 'arcdata.c' X/* X * $Header: arcdata.c,v 1.7 88/07/31 18:47:22 hyc Exp $ X */ X X/* ARC - Archive utility - ARCDATA X X Version 2.17, created on 04/22/87 at 13:09:43 X X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This file defines the external data storage used by the ARC X archive utility. X X X Language: X Computer Innovations Optimizing C86 X*/ X#include <stdio.h> X X#define DONT_DEFINE X#include "arc.h" X Xint keepbak = 0; /* true if saving the old archive */ X#if UNIX Xint image = 1; /* true to suppress CRLF/LF x-late */ X#endif X#if MTS Xint image = 0; /* true to suppress EBCDIC/ASCII x-late */ Xchar sepchr[2] = ":";/* Shared file separator */ Xchar tmpchr[2] = "-";/* Temporary file prefix */ X#endif X#if GEMDOS Xint hold = 0; /* true to pause before exit */ X#endif Xint warn = 1; /* true to print warnings */ Xint note = 1; /* true to print comments */ Xint bose = 0; /* true to be verbose */ Xint nocomp = 0; /* true to suppress compression */ Xint overlay = 0; /* true to overlay on extract */ Xint kludge = 0; /* kludge flag */ Xchar *arctemp = NULL; /* arc temp file prefix */ Xchar *password = NULL;/* encryption password pointer */ Xint nerrs = 0; /* number of errors encountered */ Xint changing = 0; /* true if archive being modified */ X Xchar hdrver; /* header version */ X XFILE *arc; /* the old archive */ XFILE *new; /* the new archive */ Xchar arcname[STRLEN]; /* storage for archive name */ Xchar bakname[STRLEN]; /* storage for backup copy name */ Xchar newname[STRLEN]; /* storage for new archive name */ Xunsigned short arcdate = 0; /* archive date stamp */ Xunsigned short arctime = 0; /* archive time stamp */ Xunsigned short olddate = 0; /* old archive date stamp */ Xunsigned short oldtime = 0; /* old archive time stamp */ Xint dosquash = 0; /* true to squash instead of crunch */ SHAR_EOF if test 2067 -ne "`wc -c < 'arcdata.c'`" then echo shar: "error transmitting 'arcdata.c'" '(should have been 2067 characters)' fi fi echo shar: "extracting 'arcdel.c'" '(2055 characters)' if test -f 'arcdel.c' then echo shar: "will not over-write existing file 'arcdel.c'" else sed 's/^X//' << \SHAR_EOF > 'arcdel.c' X/* X * $Header: arcdel.c,v 1.3 88/04/19 01:39:32 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCDEL X * X * Version 2.09, created on 02/03/86 at 22:53:27 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to delete entries in an X * archive. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X Xvoid abort(), rempath(), openarc(), closearc(), writehdr(), filecopy(); Xint match(), readhdr(); X Xvoid Xdelarc(num, arg) /* remove files from archive */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ X{ X struct heads hdr; /* header data */ X int del; /* true to delete a file */ X int did[MAXARG];/* true when argument used */ X int n; /* index */ X X if (!num) /* she must specify which */ X abort("You must tell me which files to delete!"); X X for (n = 0; n < num; n++) /* for each argument */ X did[n] = 0; /* reset usage flag */ X rempath(num, arg); /* strip off paths */ X X openarc(1); /* open archive for changes */ X X while (readhdr(&hdr, arc)) { /* while more entries in archive */ X del = 0; /* reset delete flag */ X for (n = 0; n < num; n++) { /* for each template given */ X if (match(hdr.name, arg[n])) { X del = 1; /* turn on delete flag */ X did[n] = 1; /* turn on usage flag */ X break; /* stop looking */ X } X } X X if (del) { /* skip over unwanted files */ X fseek(arc, hdr.size, 1); X if (note) X printf("Deleting file: %s\n", hdr.name); X } else { /* else copy over file data */ X writehdr(&hdr, new); /* write out header and file */ X filecopy(arc, new, hdr.size); X } X } X X hdrver = 0; /* special end of archive type */ X writehdr(&hdr, new); /* write out archive end marker */ X closearc(1); /* close archive after changes */ X X if (note) { X for (n = 0; n < num; n++) { /* report unused arguments */ X if (!did[n]) { X printf("File not found: %s\n", arg[n]); X nerrs++; X } X } X } X} SHAR_EOF if test 2055 -ne "`wc -c < 'arcdel.c'`" then echo shar: "error transmitting 'arcdel.c'" '(should have been 2055 characters)' fi fi echo shar: "extracting 'arcdos.c'" '(4684 characters)' if test -f 'arcdos.c' then echo shar: "will not over-write existing file 'arcdos.c'" else sed 's/^X//' << \SHAR_EOF > 'arcdos.c' X/* X * $Header: arcdos.c,v 1.8 88/08/01 15:07:15 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCDOS X * X * Version 1.44, created on 07/25/86 at 14:17:38 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains certain DOS level routines that assist in X * doing fancy things with an archive, primarily reading and setting the date X * and time last modified. X * X * These are, by nature, system dependant functions. But they are also, by X * nature, very expendable. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X X#if MSDOS X#include "fileio2.h" /* needed for filehand */ X#endif X X#if UNIX X#include <sys/types.h> X#include <sys/stat.h> X#include <time.h> X Xstruct timeval { /* man page said <sys/types.h>, but it */ X long tv_sec; /* really seems to be in <sys/time.h>, */ X long tv_usec; /* but why bother... */ X}; X#endif X X#if GEMDOS X#include <osbind.h> X#endif X Xchar *strcpy(), *strcat(), *malloc(); X Xvoid Xgetstamp(f, date, time) /* get a file's date/time stamp */ X#if !MTS X FILE *f; /* file to get stamp from */ X#else X char *f; /* filename "" "" */ X#endif X unsigned short *date, *time; /* storage for the stamp */ X{ X#if MSDOS X struct { X int ax, bx, cx, dx, si, di, ds, es; X } reg; X X reg.ax = 0x5700; /* get date/time */ X reg.bx = filehand(f); /* file handle */ X if (sysint21(®, ®) & 1) /* DOS call */ X printf("Get timestamp fail (%d)\n", reg.ax); X X *date = reg.dx; /* save date/time */ X *time = reg.cx; X#endif X#if GEMDOS X int fd, ret[2]; X X fd = fileno(f); X Fdatime(ret, fd, 0); X *date = ret[1]; X *time = ret[0]; X#endif X#if UNIX X struct stat buf; X struct tm *localtime(), *t; X X fstat(fileno(f), &buf); X t=localtime(&(buf.st_mtime)); X *date = (unsigned short) (((t->tm_year - 80) << 9) + X ((t->tm_mon + 1) << 5) + t->tm_mday); X *time = (unsigned short) ((t->tm_hour << 11) + X (t->tm_min << 5) + t->tm_sec / 2); X#endif X#if MTS X fortran timein(), X#if USEGFINFO X gfinfo(); X#else X fileinfo(); X#endif X int stclk[2]; X char name[24]; X struct bigtime { X int greg; X int year; X int mon; X int day; X int hour; X int min; X int sec; X int usec; X int week; X int toff; X int tzn1; X int tzn2; X } tvec; X#if USEGFINFO X static int gfflag = 0x0009, gfdummy[2] = { X 0, 0 X }; X int gfcinfo[18]; X#else X static int cattype = 2; X#endif X X strcpy(name, f); X strcat(name, " "); X#if USEGFINFO X gfcinfo[0] = 18; X gfinfo(name, name, &gfflag, gfcinfo, gfdummy, gfdummy); X timein("*IBM MICROSECONDS*", &gfcinfo[16], &tvec); X#else X fileinfo(name, &cattype, "CILCCT ", stclk); X timein("*IBM MICROSECONDS*", stclk, &tvec); X#endif X X *date = (unsigned short) (((tvec.year - 1980) << 9) + ((tvec.mon) << 5) + tvec.day); X *time = (unsigned short) ((tvec.hour << 11) + (tvec.min << 5) + tvec.sec / 2); X#endif X} X Xvoid Xsetstamp(f, date, time) /* set a file's date/time stamp */ X char *f; /* filename to stamp */ X unsigned short date, time; /* desired date, time */ X{ X#if MSDOS X FILE *ff; X struct { X int ax, bx, cx, dx, si, di, ds, es; X } reg; X X ff = fopen(f, "w+"); /* How else can I get a handle? */ X X reg.ax = 0x5701; /* set date/time */ X reg.bx = filehand(f); /* file handle */ X reg.cx = time; /* desired time */ X reg.dx = date; /* desired date */ X if (sysint21(®, ®) & 1) /* DOS call */ X printf("Set timestamp fail (%d)\n", reg.ax); X fclose(ff); X#endif X#if GEMDOS X int fd, set[2]; X X fd = Fopen(f, 0); X set[0] = time; X set[1] = date; X Fdatime(set, fd, 1); X Fclose(fd); X#endif X#if UNIX X struct tm tm; X struct timeval tvp[2]; X int utimes(); X long tmclock(); X tm.tm_sec = (time & 31) * 2; X tm.tm_min = (time >> 5) & 63; X tm.tm_hour = (time >> 11); X tm.tm_mday = date & 31; X tm.tm_mon = ((date >> 5) & 15) - 1; X tm.tm_year = (date >> 9) + 80; X tvp[0].tv_sec = tmclock(&tm); X tvp[1].tv_sec = tvp[0].tv_sec; X tvp[0].tv_usec = tvp[1].tv_usec = 0; X utimes(f, tvp); X#endif X} X X#if MSDOS Xint Xfilehand(stream) /* find handle on a file */ X struct bufstr *stream; /* file to grab onto */ X{ X return stream->bufhand; /* return DOS 2.0 file handle */ X} X#endif X X#if UNIX Xint Xizadir(filename) /* Is filename a directory? */ X char *filename; X{ X struct stat buf; X X if (stat(filename, &buf) != 0) X return (0); /* Ignore if stat fails since */ X else X return (buf.st_mode & S_IFDIR); /* bad files trapped later */ X} X#endif SHAR_EOF if test 4684 -ne "`wc -c < 'arcdos.c'`" then echo shar: "error transmitting 'arcdos.c'" '(should have been 4684 characters)' fi fi echo shar: "extracting 'arcext.c'" '(5041 characters)' if test -f 'arcext.c' then echo shar: "will not over-write existing file 'arcext.c'" else sed 's/^X//' << \SHAR_EOF > 'arcext.c' X/* X * $Header: arcext.c,v 1.5 88/06/01 19:26:31 hyc Locked $ X */ X X/* X * ARC - Archive utility - ARCEXT X * X * Version 2.19, created on 10/24/86 at 14:53:32 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to extract files from an X * archive. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X#if !MSDOS X#include <ctype.h> X#endif X Xvoid openarc(), closearc(), setstamp(); Xint free(), match(), readhdr(), unpack(); Xchar *strcpy(), *strcat(); X Xvoid Xextarc(num, arg, prt) /* extract files from archive */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ X int prt; /* true if printing */ X{ X struct heads hdr; /* file header */ X int save; /* true to save current file */ X int did[MAXARG];/* true when argument was used */ X char *i, *rindex(); /* string index */ X char **name, *malloc(); /* name pointer list, X * allocator */ X int n; /* index */ X void extfile(); X X name = (char **) malloc(num * sizeof(char *)); /* get storage for name X * pointers */ X X for (n = 0; n < num; n++) { /* for each argument */ X did[n] = 0; /* reset usage flag */ X#if !MTS X if (!(i = rindex(arg[n], '\\'))) /* find start of name */ X if (!(i = rindex(arg[n], '/'))) X if (!(i = rindex(arg[n], ':'))) X i = arg[n] - 1; X#else X if (!(i = rindex(arg[n], sepchr[0]))) X if (arg[n][0] != tmpchr[0]) X i = arg[n] - 1; X else X i = arg[n]; X#endif X name[n] = i + 1; X } X X X openarc(0); /* open archive for reading */ X X if (num) { /* if files were named */ X while (readhdr(&hdr, arc)) { /* while more files to check */ X save = 0; /* reset save flag */ X for (n = 0; n < num; n++) { /* for each template X * given */ X if (match(hdr.name, name[n])) { X save = 1; /* turn on save flag */ X did[n] = 1; /* turn on usage flag */ X break; /* stop looking */ X } X } X X if (save) /* extract if desired, else skip */ X extfile(&hdr, arg[n], prt); X else X fseek(arc, hdr.size, 1); X } X } else X while (readhdr(&hdr, arc)) /* else extract all files */ X extfile(&hdr, "", prt); X X closearc(0); /* close archive after reading */ X X if (note) { X for (n = 0; n < num; n++) { /* report unused args */ X if (!did[n]) { X printf("File not found: %s\n", arg[n]); X nerrs++; X } X } X } X free(name); X} X Xvoid Xextfile(hdr, path, prt) /* extract a file */ X struct heads *hdr; /* pointer to header data */ X char *path; /* pointer to path name */ X int prt; /* true if printing */ X{ X FILE *f, *fopen(); /* extracted file, opener */ X char buf[STRLEN]; /* input buffer */ X char fix[STRLEN]; /* fixed name buffer */ X char *i, *rindex(); /* string index */ X#ifdef LOCAL X extern int unix_names; X void lower(); X#endif /* LOCAL */ X X if (prt) { /* printing is much easier */ X unpack(arc, stdout, hdr); /* unpack file from archive */ X printf("\f"); /* eject the form */ X return; /* see? I told you! */ X } X strcpy(fix, path); /* note path name template */ X#if !MTS X if (*path) { X if (!(i = rindex(fix, '\\'))) /* find start of name */ X if (!(i = rindex(fix, '/'))) X if (!(i = rindex(fix, ':'))) X i = fix - 1; X } else i = fix -1; X#else X if (!(i = rindex(fix, sepchr[0]))) X if (fix[0] != tmpchr[0]) X i = fix - 1; X else X i = fix; X#endif X#ifdef LOCAL X if (!unix_names) X lower(hdr->name); X#endif /* LOCAL */ X strcpy(i + 1, hdr->name); /* replace template with name */ X X if (note) X printf("Extracting file: %s\n", fix); X X if (warn && !overlay) { X if (f = fopen(fix, "r")) { /* see if it exists */ X fclose(f); X printf("WARNING: File %s already exists!", fix); X fflush(stdout); X while (1) { X printf(" Overwrite it (y/n)? "); X fflush(stdout); X fgets(buf, STRLEN, stdin); X *buf = toupper(*buf); X if (*buf == 'Y' || *buf == 'N') X break; X } X if (*buf == 'N') { X printf("%s not extracted.\n", fix); X fseek(arc, hdr->size, 1); X return; X } X } X } X#if !MTS X if (!(f = fopen(fix, OPEN_W))) X#else X { X fortran create(); X void memset(); X char c_name[256]; X struct crsize { X short maxsize, cursize; X } c_size; X char c_vol[6]; X int c_type; X strcpy(c_name, fix); X strcat(c_name, " "); X c_size.maxsize = 0; X c_size.cursize = hdr->length / 4096 + 1; X memset(c_vol, 0, sizeof(c_vol)); X c_type = 0x100; X create(c_name, &c_size, c_vol, &c_type); X } X if (image) { X f = fopen(fix, "wb"); X } else X f = fopen(fix, "w"); X if (!f) X#endif X { X if (warn) { X printf("Cannot create %s\n", fix); X nerrs++; X } X fseek(arc, hdr->size, 1); X return; X } X /* now unpack the file */ X X unpack(arc, f, hdr); /* unpack file from archive */ X fclose(f); /* all done writing to file */ X#if !MTS X setstamp(fix, hdr->date, hdr->time); /* use filename for stamp */ X#endif X} SHAR_EOF if test 5041 -ne "`wc -c < 'arcext.c'`" then echo shar: "error transmitting 'arcext.c'" '(should have been 5041 characters)' fi fi echo shar: "extracting 'arcio.c'" '(7491 characters)' if test -f 'arcio.c' then echo shar: "will not over-write existing file 'arcio.c'" else sed 's/^X//' << \SHAR_EOF > 'arcio.c' X/* X * $Header: arcio.c,v 1.9 88/07/31 18:49:19 hyc Exp $ X */ X X/* ARC - Archive utility - ARCIO X X Version 2.50, created on 04/22/87 at 13:25:20 X X(C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This file contains the file I/O routines used to manipulate X an archive. X X Language: X Computer Innovations Optimizing C86 X*/ X#include <stdio.h> X#include "arc.h" X#if MTS X#include <ctype.h> X#endif X Xvoid abort(); Xint strlen(), free(); X Xint Xreadhdr(hdr, f) /* read a header from an archive */ X struct heads *hdr; /* storage for header */ X FILE *f; /* archive to read header from */ X{ X#if !MSDOS X unsigned char dummy[28]; X int i; X#endif X char name[FNLEN]; /* filename buffer */ X int try = 0;/* retry counter */ X static int first = 1; /* true only on first read */ X X if (!f) /* if archive didn't open */ X return 0; /* then pretend it's the end */ X if (feof(f)) /* if no more data */ X return 0; /* then signal end of archive */ X X if (fgetc(f) != ARCMARK) { /* check archive validity */ X if (warn) { X printf("An entry in %s has a bad header.", arcname); X nerrs++; X } X while (!feof(f)) { X try++; X if (fgetc(f) == ARCMARK) { X ungetc(hdrver = fgetc(f), f); X if (!(hdrver & 0x80) && hdrver <= ARCVER) X break; X } X } X X if (feof(f) && first) X abort("%s is not an archive", arcname); X X if (changing && warn) X abort("%s is corrupted -- changes disallowed", arcname); X X if (warn) X printf(" %d bytes skipped.\n", try); X X if (feof(f)) X return 0; X } X hdrver = fgetc(f); /* get header version */ X if (hdrver & 0x80) /* sign bit? negative? */ X abort("Invalid header in archive %s", arcname); X if (hdrver == 0) X return 0; /* note our end of archive marker */ X if (hdrver > ARCVER) { X fread(name, sizeof(char), FNLEN, f); X#if MTS X atoe(name, strlen(name)); X#endif X printf("I don't know how to handle file %s in archive %s\n", X name, arcname); X printf("I think you need a newer version of ARC.\n"); X exit(1); X } X /* amount to read depends on header type */ X X if (hdrver == 1) { /* old style is shorter */ X fread(hdr, sizeof(struct heads) - sizeof(long int), 1, f); X hdrver = 2; /* convert header to new format */ X hdr->length = hdr->size; /* size is same when not X * packed */ X } else X#if MSDOS X fread(hdr, sizeof(struct heads), 1, f); X#else X fread(dummy, 27, 1, f); X X for (i = 0; i < FNLEN; hdr->name[i] = dummy[i], i++); X#if MTS X (void) atoe(hdr->name, strlen(hdr->name)); X#endif X for (i = 0, hdr->size=0; i<4; hdr->size<<=8, hdr->size += dummy[16-i], i++); X hdr->date = (short) ((dummy[18] << 8) + dummy[17]); X hdr->time = (short) ((dummy[20] << 8) + dummy[19]); X hdr->crc = (short) ((dummy[22] << 8) + dummy[21]); X for (i = 0, hdr->length=0; i<4; hdr->length<<=8, hdr->length += dummy[26-i], i++); X#endif X X if (hdr->date > olddate X || (hdr->date == olddate && hdr->time > oldtime)) { X olddate = hdr->date; X oldtime = hdr->time; X } X first = 0; X return 1; /* we read something */ X} X Xvoid Xput_int(number, f) /* write a 2 byte integer */ X short number; X FILE *f; X{ X fputc((char) (number & 255), f); X fputc((char) (number >> 8), f); X} X Xvoid Xput_long(number, f) /* write a 4 byte integer */ X long number; X FILE *f; X{ X put_int((short) (number & 0xFFFF), f); X put_int((short) (number >> 16), f); X} X Xvoid Xwritehdr(hdr, f) /* write a header to an archive */ X struct heads *hdr; /* header to write */ X FILE *f; /* archive to write to */ X{ X fputc(ARCMARK, f); /* write out the mark of ARC */ X fputc(hdrver, f); /* write out the header version */ X if (!hdrver) /* if that's the end */ X return; /* then write no more */ X#if MSDOS X fwrite(hdr, sizeof(struct heads), 1, f); X#else X /* byte/word ordering hassles... */ X#if MTS X etoa(hdr->name, strlen(hdr->name)); X#endif X fwrite(hdr->name, 1, FNLEN, f); X put_long(hdr->size, f); X put_int(hdr->date, f); X put_int(hdr->time, f); X put_int(hdr->crc, f); X put_long(hdr->length, f); X#endif X X /* note the newest file for updating the archive timestamp */ X X if (hdr->date > arcdate X || (hdr->date == arcdate && hdr->time > arctime)) { X arcdate = hdr->date; X arctime = hdr->time; X } X} X Xvoid Xputc_tst(c, t) /* put a character, with tests */ X char c; /* character to output */ X FILE *t; /* file to write to */ X{ X c &= 0xff; X if (t) { X#if UNIX X fputc(c, t); X if (ferror(t)) X abort("Write failed"); X#else X if (fputc(c, t) == EOF) X abort("Write fail (disk full?)"); X#endif X } X} X X/* X * NOTE: The filecopy() function is used to move large numbers of bytes from X * one file to another. This particular version has been modified to improve X * performance in Computer Innovations C86 version 2.3 in the small memory X * model. It may not work as expected with other compilers or libraries, or X * indeed with different versions of the CI-C86 compiler and library, or with X * the same version in a different memory model. X * X * The following is a functional equivalent to the filecopy() routine that X * should work properly on any system using any compiler, albeit at the cost X * of reduced performance: X * X * filecopy(f,t,size) X * FILE *f, *t; long size; X * { X * while(size--) X * putc_tst(fgetc(f),t); X * } X */ X#if MSDOS X#include <fileio2.h> X Xfilecopy(f, t, size) /* bulk file copier */ X FILE *f, *t; /* files from and to */ X long size; /* bytes to copy */ X{ X char *buf; /* buffer pointer */ X char *alloc();/* buffer allocator */ X unsigned int bufl; /* buffer length */ X unsigned int coreleft(); /* space available reporter */ X unsigned int cpy; /* bytes being copied */ X long floc, tloc, fseek(); /* file pointers, setter */ X struct regval reg; /* registers for DOS calls */ X X if ((bufl = coreleft()) < 1000) /* see how much space we have */ X abort("Out of memory"); X bufl -= 1000; /* fudge factor for overhead */ X if (bufl > 60000) X bufl = 60000; /* avoid choking alloc() */ X if (bufl > size) X bufl = size; /* avoid wasting space */ X buf = alloc(bufl); /* allocate our buffer */ X X floc = fseek(f, 0L, 1); /* reset I/O system */ X tloc = fseek(t, 0L, 1); X X segread(®.si); /* set segment registers for DOS */ X X while (size > 0) { /* while more to copy */ X reg.ax = 0x3F00;/* read from handle */ X reg.bx = filehand(f); X reg.cx = bufl < size ? bufl : size; /* amount to read */ X reg.dx = buf; X if (sysint21(®, ®) & 1) X abort("Read fail"); X X cpy = reg.ax; /* amount actually read */ X reg.ax = 0x4000;/* write to handle */ X reg.bx = filehand(t); X reg.cx = cpy; X reg.dx = buf; X sysint21(®, ®); X X if (reg.ax != cpy) X abort("Write fail (disk full?)"); X X size -= (long) cpy; X } X X free(buf); /* all done with buffer */ X} X#else X Xvoid Xfilecopy(f, t, size) /* bulk file copier */ X FILE *f, *t; /* files from and to */ X long size; /* bytes to copy */ X{ X char *buf; /* buffer pointer */ X char *malloc(); /* buffer allocator */ X unsigned int bufl; /* buffer length */ X unsigned int cpy; /* bytes being copied */ X X bufl = 32760; X if (bufl > size) X bufl = size; /* don't waste space */ X X buf = malloc(bufl); X X while (size > 0) { X cpy = fread(buf, sizeof(char), X bufl < size ? bufl : (unsigned short) size, f); X if (fwrite(buf, sizeof(char), cpy, t) != cpy) X abort("Write fail (no space?)"); X size -= cpy; X } X X free(buf); X} X#endif SHAR_EOF if test 7491 -ne "`wc -c < 'arcio.c'`" then echo shar: "error transmitting 'arcio.c'" '(should have been 7491 characters)' fi fi echo shar: "extracting 'arclst.c'" '(4418 characters)' if test -f 'arclst.c' then echo shar: "will not over-write existing file 'arclst.c'" else sed 's/^X//' << \SHAR_EOF > 'arclst.c' X/* X * $Header: arclst.c,v 1.5 88/06/01 18:05:57 hyc Locked $ X */ X X/* ARC - Archive utility - ARCLST X X Version 2.39, created on 04/22/87 at 13:48:29 X X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This file contains the routines used to list the contents X of an archive. X X Language: X Computer Innovations Optimizing C86 X*/ X#include <stdio.h> X#include "arc.h" X Xvoid rempath(), openarc(), closearc(); Xint readhdr(), match(); X Xvoid Xlstarc(num, arg) /* list files in archive */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ X{ X struct heads hdr; /* header data */ X int list; /* true to list a file */ X int did[MAXARG]; /* true when argument was used */ X long tnum, tlen, tsize; /* totals */ X int n; /* index */ X void lstfile(); X X tnum = tlen = tsize = 0;/* reset totals */ X X for (n = 0; n < num; n++) /* for each argument */ X did[n] = 0; /* reset usage flag */ X rempath(num, arg); /* strip off paths */ X X if (note && !kludge) { X printf("Name Length "); X if (bose) X printf(" Stowage SF Size now"); X printf(" Date "); X if (bose) X printf(" Time CRC"); X printf("\n"); X X printf("============ ========"); X if (bose) X printf(" ======== ==== ========"); X printf(" ========="); X if (bose) X printf(" ====== ===="); X printf("\n"); X } X openarc(0); /* open archive for reading */ X X if (num) { /* if files were named */ X while (readhdr(&hdr, arc)) { /* process all archive files */ X list = 0; /* reset list flag */ X for (n = 0; n < num; n++) { /* for each template X * given */ X if (match(hdr.name, arg[n])) { X list = 1; /* turn on list flag */ X did[n] = 1; /* turn on usage flag */ X break; /* stop looking */ X } X } X X if (list) { /* if this file is wanted */ X if (!kludge) X lstfile(&hdr); /* then tell about it */ X tnum++; /* update totals */ X tlen += hdr.length; X tsize += hdr.size; X } X fseek(arc, hdr.size, 1); /* move to next header */ X } X } else X while (readhdr(&hdr, arc)) { /* else report on all files */ X if (!kludge) X lstfile(&hdr); X tnum++; /* update totals */ X tlen += hdr.length; X tsize += hdr.size; X fseek(arc, hdr.size, 1); /* skip to next header */ X } X X closearc(0); /* close archive after reading */ X X if (note && !kludge) { X printf(" ==== ========"); X if (bose) X printf(" ==== ========"); X printf("\n"); X } X if (note) { X printf("Total %6ld %8ld", tnum, tlen); X if (bose) { X if (tlen) X printf(" %3ld%%", 100L - (100L * tsize) / tlen); X else X printf(" ---"); X printf(" %8ld", tsize); X } X printf("\n"); X X for (n = 0; n < num; n++) { /* report unused args */ X if (!did[n]) { X printf("File not found: %s\n", arg[n]); X nerrs++; X } X } X } X} X Xvoid Xlstfile(hdr) /* tell about a file */ X struct heads *hdr; /* pointer to header data */ X{ X int yr, mo, dy; /* parts of a date */ X int hh, mm; /* parts of a time */ X X static char *mon[] = /* month abbreviations */ X { X "Jan", "Feb", "Mar", "Apr", X "May", "Jun", "Jul", "Aug", X "Sep", "Oct", "Nov", "Dec" X }; X X if (!note) { /* no notes means short listing */ X printf("%s\n", hdr->name); X return; X } X X yr = (hdr->date >> 9) & 0x7f; /* dissect the date */ X mo = (hdr->date >> 5) & 0x0f; X dy = hdr->date & 0x1f; X X hh = (hdr->time >> 11) & 0x1f; /* dissect the time */ X mm = (hdr->time >> 5) & 0x3f; X/* ss = (hdr->time & 0x1f) * 2; seconds, not used. */ X X printf("%-12s %8ld ", hdr->name, hdr->length); X X if (bose) { X switch (hdrver) { X case 1: X case 2: X printf(" -- "); X break; X case 3: X printf(" Packed "); X break; X case 4: X printf("Squeezed"); X break; X case 5: X case 6: X case 7: X printf("crunched"); X break; X case 8: X printf("Crunched"); X break; X case 9: X printf("Squashed"); X break; X default: X printf("Unknown!"); X } X X if (hdr->length) X printf(" %3ld%%", 100L - (100L * hdr->size) / hdr->length); X else X printf(" ---"); X printf(" %8ld ", hdr->size); X } X printf("%2d %3s %02d", dy, mon[mo - 1], (yr + 80) % 100); X X if (bose) X printf(" %2d:%02d%c %04x", X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'), X hdr->crc & 0xffff); X X printf("\n"); X} SHAR_EOF if test 4418 -ne "`wc -c < 'arclst.c'`" then echo shar: "error transmitting 'arclst.c'" '(should have been 4418 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (01/03/89)
This is part 4 (of 6) to the Arc v5.21 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # arclzw.c # arcmatch.c # arcmisc.c # arcpack.c # arcrun.c # arcs.h # This archive created: Sun Jan 1 12:48:23 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'arclzw.c'" '(22114 characters)' if test -f 'arclzw.c' then echo shar: "will not over-write existing file 'arclzw.c'" else sed 's/^X//' << \SHAR_EOF > 'arclzw.c' X/* X * $Header: arclzw.c,v 1.6 88/07/31 18:49:49 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCLZW X * X * Version 2.03, created on 10/24/86 at 11:46:22 X * X * (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to implement Lempel-Zev X * data compression, which calls for building a coding table on the fly. X * This form of compression is especially good for encoding files which X * contain repeated strings, and can often give dramatic improvements over X * traditional Huffman SQueezing. X * X * Language: Computer Innovations Optimizing C86 X * X * Programming notes: In this section I am drawing heavily on the COMPRESS X * program from UNIX. The basic method is taken from "A Technique for High X * Performance Data Compression", Terry A. Welch, IEEE Computer Vol 17, No 6 X * (June 1984), pp 8-19. Also see "Knuth's Fundamental Algorithms", Donald X * Knuth, Vol 3, Section 6.4. X * X * As best as I can tell, this method works by tracing down a hash table of code X * strings where each entry has the property: X * X * if <string> <char> is in the table then <string> is in the table. X */ X#include <stdio.h> X#include "arc.h" X Xvoid putc_pak(), abort(), putc_ncr(); Xint getc_unp(); X#if MSDOS Xchar *setmem(); X#else Xchar *memset(); X#endif X Xstatic void putcode(); X/* definitions for older style crunching */ X X#define FALSE 0 X#define TRUE !FALSE X#define TABSIZE 4096 X#define NO_PRED 0xFFFF X#define EMPTY 0xFFFF X#define NOT_FND 0xFFFF X Xstatic unsigned short inbuf; /* partial input code storage */ Xstatic int sp; /* current stack pointer */ X Xstruct entry { /* string table entry format */ X char used; /* true when this entry is in use */ X unsigned char follower; /* char following string */ X unsigned short next; /* ptr to next in collision list */ X unsigned short predecessor; /* code for preceeding string */ X}; /* string_tab[TABSIZE]; the code string table */ X X X/* definitions for the new dynamic Lempel-Zev crunching */ X X#define BITS 12 /* maximum bits per code */ X#define HSIZE 5003 /* 80% occupancy */ X#define INIT_BITS 9 /* initial number of bits/code */ X Xstatic int n_bits; /* number of bits/code */ Xstatic int maxcode; /* maximum code, given n_bits */ X#define MAXCODE(n) ((1<<(n)) - 1) /* maximum code calculation */ Xstatic int maxcodemax = 1 << BITS; /* largest possible code (+1) */ X Xstatic char buf[BITS]; /* input/output buffer */ X Xstatic unsigned char lmask[9] = /* left side masks */ X{ X 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 X}; Xstatic unsigned char rmask[9] = /* right side masks */ X{ X 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff X}; X Xstatic int offset; /* byte offset for code output */ Xstatic long in_count; /* length of input */ Xstatic long bytes_out; /* length of compressed output */ Xstatic long bytes_ref; /* output quality reference */ Xstatic long bytes_last; /* output size at last checkpoint */ Xstatic unsigned short ent; X X/* X * To save much memory (which we badly need at this point), we overlay the X * table used by the previous version of Lempel-Zev with those used by the X * new version. Since no two of these routines will be used together, we can X * safely do this. X */ X Xextern long htab[HSIZE]; /* hash code table (crunch) */ Xextern unsigned short codetab[HSIZE]; /* string code table (crunch) */ Xstatic struct entry *string_tab=(struct entry *)htab; /* old crunch string table */ X Xstatic unsigned short *prefix=codetab; /* prefix code table (uncrunch) */ Xstatic unsigned char *suffix=(unsigned char *)htab; /* suffix table (uncrunch) */ X Xstatic int free_ent; /* first unused entry */ Xstatic int firstcmp; /* true at start of compression */ Xextern unsigned char stack[HSIZE]; /* local push/pop stack */ X X/* X * block compression parameters -- after all codes are used up, and X * compression rate changes, start over. X */ X Xstatic int clear_flg; X#define CHECK_GAP 2048 /* ratio check interval */ Xstatic long checkpoint; Xvoid upd_tab(); X X/* X * the next two codes should not be changed lightly, as they must not lie X * within the contiguous general code space. X */ X#define FIRST 257 /* first free entry */ X#define CLEAR 256 /* table clear output code */ X X/* X * The cl_block() routine is called at each checkpoint to determine if X * compression would likely improve by resetting the code table. The method X * chosen to determine this is based on empirical observation that, in X * general, every 2k of input data should compress at least as well as the X * first 2k of input. X */ X Xstatic void Xcl_block(t) /* table clear for block compress */ X FILE *t; /* our output file */ X{ X checkpoint = in_count + CHECK_GAP; X X if (bytes_ref) { X if (bytes_out - bytes_last > bytes_ref) { X setmem(htab, HSIZE * sizeof(long), 0xff); X free_ent = FIRST; X clear_flg = 1; X putcode(CLEAR, t); X bytes_ref = 0; X } X } else X bytes_ref = bytes_out - bytes_last; X X bytes_last = bytes_out; /* remember where we were */ X} X X/***************************************************************** X * X * Output a given code. X * Inputs: X * code: A n_bits-bit integer. If == -1, then EOF. This assumes X * that n_bits =< (LONG)wordsize - 1. X * Outputs: X * Outputs code to the file. X * Assumptions: X * Chars are 8 bits long. X * Algorithm: X * Maintain a BITS character long buffer (so that 8 codes will X * fit in it exactly). When the buffer fills up empty it and start over. X */ X Xstatic void Xputcode(code, t) /* output a code */ X int code; /* code to output */ X FILE *t; /* where to put it */ X{ X int r_off = offset; /* right offset */ X int bits = n_bits; /* bits to go */ X char *bp = buf; /* buffer pointer */ X int n; /* index */ X X register int ztmp; X X if (code >= 0) { /* if a real code *//* Get to the first byte. */ X bp += (r_off >> 3); X r_off &= 7; X X /* X * Since code is always >= 8 bits, only need to mask the X * first hunk on the left. X */ X ztmp = (code << r_off) & lmask[r_off]; X *bp = (*bp & rmask[r_off]) | ztmp; X bp++; X bits -= (8 - r_off); X code >>= (8 - r_off); X X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ X if (bits >= 8) { X *bp++ = code; X code >>= 8; X bits -= 8; X } X /* Last bits. */ X if (bits) X *bp = code; X offset += n_bits; X X if (offset == (n_bits << 3)) { X bp = buf; X bits = n_bits; X bytes_out += bits; X do X putc_pak(*bp++, t); X while (--bits); X offset = 0; X } X /* X * If the next entry is going to be too big for the code X * size, then increase it, if possible. X */ X if (free_ent > maxcode || clear_flg > 0) { X /* X * Write the whole buffer, because the input side X * won't discover the size increase until after X * it has read it. X */ X if (offset > 0) { X bp = buf; /* reset pointer for writing */ X bytes_out += n = n_bits; X while (n--) X putc_pak(*bp++, t); X } X offset = 0; X X if (clear_flg) { /* reset if clearing */ X maxcode = MAXCODE(n_bits = INIT_BITS); X clear_flg = 0; X } else {/* else use more bits */ X n_bits++; X if (n_bits == BITS) X maxcode = maxcodemax; X else X maxcode = MAXCODE(n_bits); X } X } X } else { /* dump the buffer on EOF */ X bytes_out += n = (offset + 7) / 8; X X if (offset > 0) X while (n--) X putc_pak(*bp++, t); X offset = 0; X } X} X X/***************************************************************** X * X * Read one code from the standard input. If EOF, return -1. X * Inputs: X * cmpin X * Outputs: X * code or -1 is returned. X */ X Xstatic int Xgetcode(f) /* get a code */ X FILE *f; /* file to get from */ X{ X int code; X static int loffset = 0, size = 0; X int r_off, bits; X unsigned char *bp = (unsigned char *) buf; X X if (clear_flg > 0 || loffset >= size || free_ent > maxcode) { X /* X * If the next entry will be too big for the current code X * size, then we must increase the size. This implies X * reading a new buffer full, too. X */ X if (free_ent > maxcode) { X n_bits++; X if (n_bits == BITS) X maxcode = maxcodemax; /* won't get any bigger X * now */ X else X maxcode = MAXCODE(n_bits); X } X if (clear_flg > 0) { X maxcode = MAXCODE(n_bits = INIT_BITS); X clear_flg = 0; X } X for (size = 0; size < n_bits; size++) { X if ((code = getc_unp(f)) == EOF) X break; X else X buf[size] = (char) code; X } X if (size <= 0) X return -1; /* end of file */ X X loffset = 0; X /* Round size down to integral number of codes */ X size = (size << 3) - (n_bits - 1); X } X r_off = loffset; X bits = n_bits; X X /* X * Get to the first byte. X */ X bp += (r_off >> 3); X r_off &= 7; X X /* Get first part (low order bits) */ X code = (*bp++ >> r_off); X bits -= 8 - r_off; X r_off = 8 - r_off; /* now, offset into code word */ X X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ X if (bits >= 8) { X code |= *bp++ << r_off; X r_off += 8; X bits -= 8; X } X /* high order bits. */ X code |= (*bp & rmask[bits]) << r_off; X loffset += n_bits; X X return code & MAXCODE(BITS); X} X X/* X * compress a file X * X * Algorithm: use open addressing double hashing (no chaining) on the prefix X * code / next character combination. We do a variant of Knuth's algorithm D X * (vol. 3, sec. 6.4) along with G. Knott's relatively-prime secondary probe. X * Here, the modular division first probe is gives way to a faster X * exclusive-or manipulation. Also do block compression with an adaptive X * reset, where the code table is cleared when the compression ratio X * decreases, but after the table fills. The variable-length output codes X * are re-sized at this point, and a special CLEAR code is generated for the X * decompressor. X */ X Xvoid Xinit_cm(t) /* initialize for compression */ X FILE *t; /* where compressed file goes */ X{ X offset = 0; X bytes_out = bytes_last = 1; X bytes_ref = 0; X clear_flg = 0; X in_count = 1; X checkpoint = CHECK_GAP; X maxcode = MAXCODE(n_bits = INIT_BITS); X free_ent = FIRST; X setmem(htab, HSIZE * sizeof(long), 0xff); X n_bits = INIT_BITS; /* set starting code size */ X X putc_pak(BITS, t); /* note our max code length */ X X firstcmp = 1; /* next byte will be first */ X} X Xvoid Xputc_cm(c, t) /* compress a character */ X unsigned char c; /* character to compress */ X FILE *t; /* where to put it */ X{ X static long fcode; X static int hshift; X int i; X int disp; X X if (firstcmp) { /* special case for first byte */ X ent = c; /* remember first byte */ X X hshift = 0; X for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L) X hshift++; X hshift = 8 - hshift; /* set hash code range bound */ X X firstcmp = 0; /* no longer first */ X return; X } X in_count++; X X fcode = (long) (((long) c << BITS) + ent); X i = (c << hshift) ^ ent;/* xor hashing */ X X if (htab[i] == fcode) { X ent = codetab[i]; X return; X } else if (htab[i] < 0) /* empty slot */ X goto nomatch; X disp = HSIZE - i; /* secondary hash (after G.Knott) */ X if (i == 0) X disp = 1; X Xprobe: X if ((i -= disp) < 0) X i += HSIZE; X X if (htab[i] == fcode) { X ent = codetab[i]; X return; X } X if (htab[i] > 0) X goto probe; X Xnomatch: X putcode(ent, t); X ent = c; X if (free_ent < maxcodemax) { X codetab[i] = free_ent++; /* code -> hashtable */ X htab[i] = fcode; X } X if (in_count >= checkpoint) X cl_block(t); /* check for adaptive reset */ X} X Xlong Xpred_cm(t) /* finish compressing a file */ X FILE *t; /* where to put it */ X{ X putcode(ent, t); /* put out the final code */ X putcode(-1, t); /* tell output we are done */ X X return bytes_out; /* say how big it got */ X} X X/* X * Decompress a file. This routine adapts to the codes in the file building X * the string table on-the-fly; requiring no table to be stored in the X * compressed file. The tables used herein are shared with those of the X * compress() routine. See the definitions above. X */ X Xvoid Xdecomp(f, t) /* decompress a file */ X FILE *f; /* file to read codes from */ X FILE *t; /* file to write text to */ X{ X unsigned char *stackp; X int finchar; X int code, oldcode, incode; X X if ((code = getc_unp(f)) != BITS) X abort("File packed with %d bits, I can only handle %d", code, BITS); X X n_bits = INIT_BITS; /* set starting code size */ X clear_flg = 0; X X /* X * As above, initialize the first 256 entries in the table. X */ X maxcode = MAXCODE(n_bits = INIT_BITS); X setmem(prefix, 256 * sizeof(short), 0); /* reset decode string table */ X for (code = 255; code >= 0; code--) X suffix[code] = (unsigned char) code; X X free_ent = FIRST; X X finchar = oldcode = getcode(f); X if (oldcode == -1) /* EOF already? */ X return; /* Get out of here */ X putc_ncr((unsigned char) finchar, t); /* first code must be 8 bits=char */ X stackp = stack; X X while ((code = getcode(f)) > -1) { X if (code == CLEAR) { /* reset string table */ X setmem(prefix, 256 * sizeof(short), 0); X clear_flg = 1; X free_ent = FIRST - 1; X if ((code = getcode(f)) == -1) /* O, untimely death! */ X break; X } X incode = code; X /* X * Special case for KwKwK string. X */ X if (code >= free_ent) { X if (code > free_ent) { X if (warn) { X printf("Corrupted compressed file.\n"); X printf("Invalid code %d when max is %d.\n", X code, free_ent); X } X nerrs++; X return; X } X *stackp++ = finchar; X code = oldcode; X } X /* X * Generate output characters in reverse order X */ X while (code >= 256) { X *stackp++ = suffix[code]; X code = prefix[code]; X } X *stackp++ = finchar = suffix[code]; X X /* X * And put them out in forward order X */ X do X putc_ncr(*--stackp, t); X while (stackp > stack); X X /* X * Generate the new entry. X */ X if ((code = free_ent) < maxcodemax) { X prefix[code] = (unsigned short) oldcode; X suffix[code] = finchar; X free_ent = code + 1; X } X /* X * Remember previous code. X */ X oldcode = incode; X } X} X X X/************************************************************************* X * Please note how much trouble it can be to maintain upwards * X * compatibility. All that follows is for the sole purpose of unpacking * X * files which were packed using an older method. * X *************************************************************************/ X X X/* X * The h() pointer points to the routine to use for calculating a hash value. X * It is set in the init routines to point to either of oldh() or newh(). X * X * oldh() calculates a hash value by taking the middle twelve bits of the square X * of the key. X * X * newh() works somewhat differently, and was tried because it makes ARC about X * 23% faster. This approach was abandoned because dynamic Lempel-Zev X * (above) works as well, and packs smaller also. However, inadvertent X * release of a developmental copy forces us to leave this in. X */ X Xstatic unsigned short(*h) (); /* pointer to hash function */ X Xstatic unsigned short Xoldh(pred, foll) /* old hash function */ X unsigned short pred; /* code for preceeding string */ X unsigned char foll; /* value of following char */ X{ X long local; /* local hash value */ X X local = ((pred + foll) | 0x0800) & 0xFFFF; /* create the hash key */ X local *= local; /* square it */ X return (local >> 6) & 0x0FFF; /* return the middle 12 bits */ X} X Xstatic unsigned short Xnewh(pred, foll) /* new hash function */ X unsigned short pred; /* code for preceeding string */ X unsigned char foll; /* value of following char */ X{ X return (((pred + foll) & 0xFFFF) * 15073) & 0xFFF; /* faster hash */ X} X X/* X * The eolist() function is used to trace down a list of entries with X * duplicate keys until the last duplicate is found. X */ X Xstatic unsigned short Xeolist(index) /* find last duplicate */ X unsigned short index; X{ X int temp; X X while (temp = string_tab[index].next) /* while more duplicates */ X index = temp; X X return index; X} X X/* X * The hash() routine is used to find a spot in the hash table for a new X * entry. It performs a "hash and linear probe" lookup, using h() to X * calculate the starting hash value and eolist() to perform the linear X * probe. This routine DOES NOT detect a table full condition. That MUST be X * checked for elsewhere. X */ X Xstatic unsigned short Xhash(pred, foll) /* find spot in the string table */ X unsigned short pred; /* code for preceeding string */ X unsigned char foll; /* char following string */ X{ X unsigned short local, tempnext; /* scratch storage */ X struct entry *ep; /* allows faster table handling */ X X local = (*h) (pred, foll); /* get initial hash value */ X X if (!string_tab[local].used) /* if that spot is free */ X return local; /* then that's all we need */ X X else { /* else a collision has occured */ X local = eolist(local); /* move to last duplicate */ X X /* X * We must find an empty spot. We start looking 101 places X * down the table from the last duplicate. X */ X X tempnext = (local + 101) & 0x0FFF; X ep = &string_tab[tempnext]; /* initialize pointer */ X X while (ep->used) { /* while empty spot not found */ X if (++tempnext == TABSIZE) { /* if we are at the end */ X tempnext = 0; /* wrap to beginning of table */ X ep = string_tab; X } else X ++ep; /* point to next element in table */ X } X X /* X * local still has the pointer to the last duplicate, while X * tempnext has the pointer to the spot we found. We use X * this to maintain the chain of pointers to duplicates. X */ X X string_tab[local].next = tempnext; X X return tempnext; X } X} X X/* X * The init_tab() routine is used to initialize our hash table. You realize, X * of course, that "initialize" is a complete misnomer. X */ X Xstatic void Xinit_tab() X{ /* set ground state in hash table */ X unsigned int i; /* table index */ X X setmem((char *) string_tab, sizeof(string_tab), 0); X X for (i = 0; i < 256; i++) /* list all single byte strings */ X upd_tab(NO_PRED, i); X X inbuf = EMPTY; /* nothing is in our buffer */ X} X X/* X * The upd_tab routine is used to add a new entry to the string table. As X * previously stated, no checks are made to ensure that the table has any X * room. This must be done elsewhere. X */ X Xvoid Xupd_tab(pred, foll) /* add an entry to the table */ X unsigned short pred; /* code for preceeding string */ X unsigned short foll; /* character which follows string */ X{ X struct entry *ep; /* pointer to current entry */ X X /* calculate offset just once */ X X ep = &string_tab[hash(pred, foll)]; X X ep->used = TRUE; /* this spot is now in use */ X ep->next = 0; /* no duplicates after this yet */ X ep->predecessor = pred; /* note code of preceeding string */ X ep->follower = foll; /* note char after string */ X} X X/* X * This algorithm encoded a file into twelve bit strings (three nybbles). The X * gocode() routine is used to read these strings a byte (or two) at a time. X */ X Xstatic int Xgocode(fd) /* read in a twelve bit code */ X FILE *fd; /* file to get code from */ X{ X unsigned short localbuf, returnval; X int temp; X X if (inbuf == EMPTY) { /* if on a code boundary */ X if ((temp = getc_unp(fd)) == EOF) /* get start of next X * code */ X return EOF; /* pass back end of file status */ X localbuf = temp & 0xFF; /* mask down to true byte value */ X if ((temp = getc_unp(fd)) == EOF) X /* get end of code, * start of next */ X return EOF; /* this should never happen */ X inbuf = temp & 0xFF; /* mask down to true byte value */ X X returnval = ((localbuf << 4) & 0xFF0) + ((inbuf >> 4) & 0x00F); X inbuf &= 0x000F;/* leave partial code pending */ X } else { /* buffer contains first nybble */ X if ((temp = getc_unp(fd)) == EOF) X return EOF; X localbuf = temp & 0xFF; X X returnval = localbuf + ((inbuf << 8) & 0xF00); X inbuf = EMPTY; /* note no hanging nybbles */ X } X return returnval; /* pass back assembled code */ X} X Xstatic void Xpush(c) /* push char onto stack */ X int c; /* character to push */ X{ X stack[sp] = ((char) c); /* coerce integer into a char */ X X if (++sp >= TABSIZE) X abort("Stack overflow\n"); X} X Xstatic int Xpop() X{ /* pop character from stack */ X if (sp > 0) X return ((int) stack[--sp]); /* leave ptr at next empty X * slot */ X X else X return EMPTY; X} X X/***** LEMPEL-ZEV DECOMPRESSION *****/ X Xstatic int code_count; /* needed to detect table full */ Xstatic int firstc; /* true only on first character */ X Xvoid Xinit_ucr(inew) /* get set for uncrunching */ X int inew; /* true to use new hash function */ X{ X if (inew) /* set proper hash function */ X h = newh; X else X h = oldh; X X sp = 0; /* clear out the stack */ X init_tab(); /* set up atomic code definitions */ X code_count = TABSIZE - 256; /* note space left in table */ X firstc = 1; /* true only on first code */ X} X Xint Xgetc_ucr(f) /* get next uncrunched byte */ X FILE *f; /* file containing crunched data */ X{ X int code, newcode; X static int oldcode, finchar; X struct entry *ep; /* allows faster table handling */ X X if (firstc) { /* first code is always known */ X firstc = FALSE; /* but next will not be first */ X oldcode = gocode(f); X return finchar = string_tab[oldcode].follower; X } X if (!sp) { /* if stack is empty */ X if ((code = newcode = gocode(f)) == EOF) X return EOF; X X ep = &string_tab[code]; /* initialize pointer */ X X if (!ep->used) {/* if code isn't known */ X code = oldcode; X ep = &string_tab[code]; /* re-initialize pointer */ X push(finchar); X } X while (ep->predecessor != NO_PRED) { X push(ep->follower); /* decode string backwards */ X code = ep->predecessor; X ep = &string_tab[code]; X } X X push(finchar = ep->follower); /* save first character also */ X X /* X * The above loop will terminate, one way or another, with X * string_tab[code].follower equal to the first character in X * the string. X */ X X if (code_count) { /* if room left in string table */ X upd_tab(oldcode, finchar); X --code_count; X } X oldcode = newcode; X } X return pop(); /* return saved character */ X} SHAR_EOF if test 22114 -ne "`wc -c < 'arclzw.c'`" then echo shar: "error transmitting 'arclzw.c'" '(should have been 22114 characters)' fi fi echo shar: "extracting 'arcmatch.c'" '(3257 characters)' if test -f 'arcmatch.c' then echo shar: "will not over-write existing file 'arcmatch.c'" else sed 's/^X//' << \SHAR_EOF > 'arcmatch.c' X/* X * $Header: arcmatch.c,v 1.6 88/07/31 18:50:18 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCMATCH X * X * Version 2.17, created on 12/17/85 at 20:32:18 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains service routines needed to maintain an X * archive. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X Xint strcmp(), strlen(); Xvoid abort(); Xchar *strcpy(); X Xint Xmatch(n, t) /* test name against template */ X char *n; /* name to test */ X char *t; /* template to test against */ X{ X#ifdef LOCAL X extern int unix_names; X#endif /* LOCAL */ X#if MTS X fortran patbuild(), patmatch(), patfree(); X static int patlen = (-1); X static int patwork = 0; X static int patswch = 0; X char patccid[4]; X static char patchar[2] = "?"; X static char oldtemp[16] = 0; X int namlen, RETCODE; X X if (strcmp(t, oldtemp)) { X if (patwork) X patfree(&patwork); X strcpy(oldtemp, t); X patlen = strlen(oldtemp); X patbuild(oldtemp, &patlen, &patwork, &patswch, patccid, patchar, _retcode RETCODE); X if (RETCODE > 8) { X printf("MTS: patbuild returned %d\n", RETCODE); X abort("bad wildcard in filename"); X } X } X namlen = strlen(n); X patmatch(n, &namlen, &patwork, _retcode RETCODE); X switch (RETCODE) { X case 0: X return (1); X case 4: X return (0); X default: X abort("wildcard pattern match failed"); X } X} X X#else X#if !UNIX X upper(n); X upper(t); /* avoid case problems */ X#endif /* UNIX */ X#if GEMDOS X char *strstr(), *i; /* allow "*.*" to mean '*' */ X if (i=strstr(t,"*.*")) { X i++; X *i='\0'; X } X return(pnmatch(n, t, 0)); X#else X /* first match name part */ X X#ifdef LOCAL X if (!unix_names) { X upper(n); X upper(t); X } X#endif /* LOCAL */ X X while ((*n && *n != '.') || (*t && *t != '.')) { X if (*n != *t && *t != '?') { /* match fail? */ X if (*t != '*') /* wildcard fail? */ X return 0; /* then no match */ X else { /* else jump over wildcard */ X while (*n && *n != '.') X n++; X while (*t && *t != '.') X t++; X break; /* name part matches wildcard */ X } X } else { /* match good for this char */ X n++; /* advance to next char */ X t++; X } X } X X if (*n && *n == '.') X n++; /* skip extension delimiters */ X if (*t && *t == '.') X t++; X X /* now match name part */ X X while (*n || *t) { X if (*n != *t && *t != '?') { /* match fail? */ X if (*t != '*') /* wildcard fail? */ X return 0; /* then no match */ X else X return 1; /* else good enough */ X } else { /* match good for this char */ X n++; /* advance to next char */ X t++; X } X } X X return 1; /* match worked */ X#endif /* GEMDOS */ X} X#endif X Xvoid Xrempath(nargs, arg) /* remove paths from filenames */ X int nargs; /* number of names */ X char *arg[]; /* pointers to names */ X{ X char *i, *rindex(); /* string index, reverse indexer */ X int n; /* index */ X X for (n = 0; n < nargs; n++) { /* for each supplied name */ X if (!(i = rindex(arg[n], '\\'))) /* search for end of X * path */ X if (!(i = rindex(arg[n], '/'))) X i = rindex(arg[n], ':'); X if (i) /* if path was found */ X arg[n] = i + 1; /* then skip it */ X } X} SHAR_EOF if test 3257 -ne "`wc -c < 'arcmatch.c'`" then echo shar: "error transmitting 'arcmatch.c'" '(should have been 3257 characters)' fi fi echo shar: "extracting 'arcmisc.c'" '(8946 characters)' if test -f 'arcmisc.c' then echo shar: "will not over-write existing file 'arcmisc.c'" else sed 's/^X//' << \SHAR_EOF > 'arcmisc.c' X/* X * Miscellaneous routines to get ARC running on non-MSDOS systems... X * $Header: arcmisc.c,v 1.8 88/07/31 18:50:56 hyc Exp $ X */ X X#include <stdio.h> X#include <ctype.h> X#include "arc.h" X X#if MSDOS X#include <dir.h> X#include <stat.h> X#endif X X#if GEMDOS X#include <osbind.h> X#include <stat.h> Xchar *index(), *rindex(); X Xvoid Xexitpause() X{ X while (Cconis()) X Cnecin(); X fprintf(stderr, "Press any key to continue: "); X fflush(stderr); X Cnecin(); X fprintf(stderr, "\n"); X} X Xint Xchdir(dirname) X char *dirname; X{ X char *i; X int drv; X X i = dirname; X if ((i = index(dirname, ':')) != NULL) { X drv = i[-1]; X i++; /* Move past device spec */ X if (drv > '\'') X drv -= 'a'; X else X drv -= 'A'; X if (drv >= 0 && drv < 16) X Dsetdrv(drv); X } X if (*i != '\0') X return (Dsetpath(i)); X} X#endif X X#if UNIX X#include <sys/types.h> X#include <sys/dir.h> X#include <sys/stat.h> X int rename(), unlink(); X#endif X X#if 0 X#include <dirent.h> X#define DIRECT dirent X#else X#define DIRECT direct X#endif X X#if BSD Xchar * Xmemset(s, c, n) /* oops. Thought it was standard BSD, but my Sun */ X char *s; /* fooled me again. -- hyc */ X int c, n; X{ X register int i; X for(i=0;i<n;i++) X s[i]=c; X return(s); X} X#endif X Xchar *strcpy(), *strcat(), *malloc(); Xint strlen(), strcmp(), match(); X Xint Xmove(oldnam, newnam) X char *oldnam, *newnam; X{ X FILE *fopen(), *old, *mnew; X#if !MTS X struct stat oldstat; X#endif X char *strcpy(); X void filecopy(); X#if GEMDOS X if (Frename(0, oldnam, newnam)) X#else X if (rename(oldnam, newnam)) X#endif X#if !MTS X { X if (stat(oldnam, &oldstat)) /* different partition? */ X return (-1); X old = fopen(oldnam, OPEN_R); X if (old == NULL) X return (-1); X mnew = fopen(newnam, OPEN_W); X if (mnew == NULL) X return (-1); X filecopy(old, mnew, oldstat.st_size); X return(unlink(oldnam)); X } X return 0; X#else X return(-1); X#endif X} X Xstatic void X_makefn(source, dest) X char *source; X char *dest; X{ X int j; X#if MSDOS X char *setmem(); X#else X char *memset(); X#endif X X setmem(dest, 17, 0); /* clear result field */ X for (j = 0; *source && *source != '.'; ++source) X if (j < 8) X dest[j++] = *source; X for (j = 9; *source; ++source) X if (j < 13) X dest[j++] = *source; X} X/* X * make a file name using a template X */ X Xchar * Xmakefnam(rawfn, template, result) X char *rawfn; /* the original file name */ X char *template; /* the template data */ X char *result; /* where to place the result */ X{ X char et[17], er[17], rawbuf[STRLEN], *i, *rindex(); X X *rawbuf = 0; X strcpy(rawbuf, rawfn); X#if MTS X i = rawbuf; X if (rawbuf[0] == tmpchr[0]) { X i++; X strcpy(rawfn, i); X } else X#endif X if ((i = rindex(rawbuf, CUTOFF))) { X i++; X strcpy(rawfn, i); X } X#if DOS X else if ((i = rindex(rawbuf, ':'))) { X i++; X strcpy(rawfn, i); X } X#endif X if (i) X *i = 0; X else X *rawbuf = 0; X X _makefn(template, et); X _makefn(rawfn, er); X *result = 0; /* assure no data */ X strcat(result, rawbuf); X strcat(result, er[0] ? er : et); X strcat(result, er[9] ? er + 9 : et + 9); X return ((char *) &result[0]); X} X X#if MSDOS || SYSV X Xint Xalphasort(dirptr1, dirptr2) X struct DIRECT **dirptr1, **dirptr2; X{ X return (strcmp((*dirptr1)->d_name, (*dirptr2)->d_name)); X} X X#endif X X#ifdef LOCAL Xvoid Xlower(string) X char *string; X{ X char *p; X X for (p = string; *p; p++) X if (isupper(*p)) X *p = tolower(*p); X} X#endif /* LOCAL */ X Xvoid Xupper(string) X char *string; X{ X char *p; X X for (p = string; *p; p++) X if (islower(*p)) X *p = toupper(*p); X} X/* VARARGS1 */ Xvoid Xabort(s, arg1, arg2, arg3) X char *s; X{ X fprintf(stderr, "ARC: "); X fprintf(stderr, s, arg1, arg2, arg3); X fprintf(stderr, "\n"); X#if UNIX X perror("UNIX"); X#endif X#if GEMDOS X exitpause(); X#endif X exit(1); X} X X#if !MTS X Xchar * Xgcdir(dirname) X char *dirname; X X{ X char *getwd(); X#if GEMDOS X int drv; X char *buf; X#endif X if (dirname == NULL || strlen(dirname) == 0) X dirname = (char *) malloc(1024); X X#if !GEMDOS X getwd(dirname); X#else X buf = dirname; X *buf++ = (drv = Dgetdrv()) + 'A'; X *buf++ = ':'; X Dgetpath(buf, 0); X#endif X return (dirname); X} X X#if UNIX Xchar *pattern; /* global so that fmatch can use it */ X#endif X Xchar * Xdir(filename) /* get files, one by one */ X char *filename; /* template, or NULL */ X{ X#if GEMDOS X static int Nnum = 0; X static DMABUFFER dbuf, *saved; X char *name; X X if (Nnum == 0) { /* first call */ X saved = (DMABUFFER *) Fgetdta(); X Fsetdta(&dbuf); X if (Fsfirst(filename, 0) == 0) { X name = malloc(FNLEN); X strcpy(name, dbuf.d_fname); X Nnum++; X return (name); X } else { X Fsetdta(saved); X return (NULL); X } X } else { X if (Fsnext() == 0) { X name = malloc(FNLEN); X strcpy(name, dbuf.d_fname); X return (name); X } else { X Nnum = 0; X Fsetdta(saved); X return (NULL); X } X } X} X#else X static struct DIRECT **namelist; X static char **NameList; X static char namecopy[STRLEN], *dirname; X#if UNIX X int alphasort(); X int scandir(); X#endif /* UNIX */ X int fmatch(), free(); X static int Nnum = 0, ii; X char *rindex(); X X X if (Nnum == 0) { /* first call */ X strcpy(namecopy,filename); X if(pattern=rindex(namecopy,CUTOFF)) { X *pattern = 0; X pattern++; X dirname = namecopy; X } else { X pattern = filename; X dirname = "."; X } X Nnum = scandir(dirname, &namelist, fmatch, alphasort); X NameList = (char **) malloc(Nnum * sizeof(char *)); X for (ii = 0; ii < Nnum; ii++) { X (NameList)[ii] = malloc(strlen(namelist[ii]->d_name) + 1); X strcpy((NameList)[ii], namelist[ii]->d_name); X } X ii = 0; X } X if (ii >= Nnum) { /* all out of files */ X if (Nnum) { /* there were some files found */ X for (ii = 0; ii < Nnum; ii++) X free(namelist[ii]); X free(namelist); X } X Nnum = 0; X return (NULL); X } else { X return ((NameList)[ii++]); X } X} X X/* X * Filename match - here, * matches everything X */ X Xint Xfmatch(direntry) X struct DIRECT *direntry; X{ X char *string; X X string = direntry->d_name; X X if (!strcmp(pattern, "") || !strcmp(pattern, "*.*") || !strcmp(pattern, "*")) X return (1); X#if UNIX X return(!strcmp(pattern, string)); X#else X return (match(string, pattern)); X#endif X} X#endif /* GEMDOS */ X#else X/* dir code for MTS under Bell Labs C... */ X Xchar * Xdir(filepattern) X char *filepattern; /* template or NULL */ X{ X char *malloc(), *index(); X#if USECATSCAN X fortran void catscan(), fileinfo(); X X struct catname { X short len; X char name[257]; X } pattern; X X struct catval { X int maxlen; X int actlen; X char name[257]; X } catreturn; X X char *i; X int j, RETCODE; X X static int catptr = 0; X static int catflag = 0x200; X static int cattype = 1; X static int patflag = 0; X X catreturn.maxlen = 256; X X if (patflag) { X patflag = 0; X catptr = 0; X return (NULL); X } X if (filepattern) { X strcpy(pattern.name, filepattern); X pattern.len = strlen(filepattern); X if (!index(filepattern, '?')) X patflag = 1; X } X if (patflag) { X fileinfo(&pattern, &cattype, "CINAME ", &catreturn, _retcode RETCODE); X catptr = RETCODE ? 0 : 1; X } else X catscan(&pattern, &catflag, &cattype, &catreturn, &catptr); X X if (!catptr) X return (NULL); X else { X char *k; X X k = index(catreturn.name, ' '); X if (k) X *k = 0; X else { X j = catreturn.actlen; X catreturn.name[j] = 0; X } X k = catreturn.name; X if (catreturn.name[0] == tmpchr[0]) X k++; X else if ((k = index(catreturn.name, sepchr[0]))) X k++; X else X k = catreturn.name; X j = strlen(k); X i = malloc(++j); X strcpy(i, k); X return (i); X } X#else X fortran void gfinfo(); X static char gfname[24]; X static char pattern[20]; X static int gfdummy[2] = { X 0, 0 X }, gfflags; X int i, RETCODE; X char *j, *k; X X if (filepattern) { X strcpy(pattern, filepattern); X strcat(pattern, " "); X for (i = 20; i < 24; i++) X gfname[i] = '\0'; X if (index(pattern, '?')) X gfflags = 0x0C; X else X gfflags = 0x09; X } else if (gfflags == 0x09) X return (NULL); X X gfinfo(pattern, gfname, &gfflags, gfdummy, gfdummy, gfdummy, _retcode RETCODE); X if (RETCODE) X return (NULL); X else { X k = index(gfname, ' '); X *k = '\0'; X k = gfname; X if (gfname[0] == tmpchr[0]) X k++; X else if ((k = index(gfname, sepchr[0]))) X k++; X else X k = gfname; X i = strlen(k); X j = malloc(++i); X strcpy(j, k); X return (j); X } X#endif X} X Xint Xunlink(path) X char *path; /* name of file to delete */ X{ X fortran void destroy(); X int RETCODE; X X char name[258]; X X strcpy(name, path); X strcat(name, " "); X destroy(name, _retcode RETCODE); X if (RETCODE) X return (-1); X else X return (0); X} X#endif SHAR_EOF if test 8946 -ne "`wc -c < 'arcmisc.c'`" then echo shar: "error transmitting 'arcmisc.c'" '(should have been 8946 characters)' fi fi echo shar: "extracting 'arcpack.c'" '(7438 characters)' if test -f 'arcpack.c' then echo shar: "will not over-write existing file 'arcpack.c'" else sed 's/^X//' << \SHAR_EOF > 'arcpack.c' X/* X * $Header: arcpack.c,v 1.12 88/11/16 17:18:06 hyc Exp $ X */ X X/* ARC - Archive utility - ARCPACK X X Version 3.49, created on 04/21/87 at 11:26:51 X X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This file contains the routines used to compress a file X when placing it in an archive. X X Language: X Computer Innovations Optimizing C86 X*/ X#include <stdio.h> X#include "arc.h" X#if MTS X#include <ctype.h> X#endif X Xvoid setcode(), sqinit_cm(), sqputc_cm(), init_cm(), putc_cm(); Xvoid filecopy(), abort(), putc_tst(), init_sq(), scan_sq(); Xint getch(), addcrc(); X X/* stuff for non-repeat packing */ X X#define DLE 0x90 /* repeat sequence marker */ X Xstatic unsigned char state; /* current packing state */ X X/* non-repeat packing states */ X X#define NOHIST 0 /* don't consider previous input */ X#define SENTCHAR 1 /* lastchar set, no lookahead yet */ X#define SENDNEWC 2 /* run over, send new char next */ X#define SENDCNT 3 /* newchar set, send count next */ X X/* packing results */ X Xstatic long stdlen; /* length for standard packing */ Xstatic short crcval; /* CRC check value */ X Xvoid Xpack(f, t, hdr) /* pack file into an archive */ X FILE *f, *t; /* source, destination */ X struct heads *hdr; /* pointer to header data */ X{ X int c; /* one character of stream */ X long ncrlen; /* length after packing */ X long huflen; /* length after squeezing */ X long lzwlen; /* length after crunching */ X long pred_sq(), file_sq(); /* stuff for squeezing */ X long pred_cm(), sqpred_cm(); /* dynamic crunching cleanup */ X long tloc, ftell(); /* start of output */ X int getch(); X int getc_ncr(); X void putc_pak(); X X /* first pass - see which method is best */ X X tloc = ftell(t); /* note start of output */ X X if (!nocomp) { /* if storage kludge not active */ X if (note) { X printf(" analyzing, "); X fflush(stdout); X } X state = NOHIST; /* initialize ncr packing */ X stdlen = ncrlen = 0; /* reset size counters */ X crcval = 0; /* initialize CRC check value */ X setcode(); /* initialize encryption */ X init_sq(); /* initialize for squeeze scan */ X X if (dosquash) { X sqinit_cm(); X while ((c = getch(f)) != EOF) { /* for each byte of file */ X ncrlen++; /* one more packed byte */ X scan_sq(c); /* see what squeezing can do */ X sqputc_cm(c, t); /* see what squashing X * can do */ X } X lzwlen = sqpred_cm(t); X } else { X init_cm(t); /* initialize for crunching */ X X while ((c = getc_ncr(f)) != EOF) { /* for each byte of file */ X ncrlen++; /* one more packed byte */ X scan_sq(c); /* see what squeezing can do */ X putc_cm(c, t); /* see what crunching can do */ X } X lzwlen = pred_cm(t); /* finish up after crunching */ X } X huflen = pred_sq(); /* finish up after squeezing */ X } else { /* else kludge the method */ X stdlen = 0; /* make standard look best */ X ncrlen = huflen = lzwlen = 1; X } X X /* standard set-ups common to all methods */ X X fseek(f, 0L, 0); /* rewind input */ X hdr->crc = crcval; /* note CRC check value */ X hdr->length = stdlen; /* set actual file length */ X state = NOHIST; /* reinitialize ncr packing */ X setcode(); /* reinitialize encryption */ X X /* choose and use the shortest method */ X X if (kludge && note) X printf("\n\tS:%ld P:%ld S:%ld C:%ld,\t ", X stdlen, ncrlen, huflen, lzwlen); X X if (stdlen <= ncrlen && stdlen <= huflen && stdlen <= lzwlen) { X if (note) { X printf("storing, "); /* store without compression */ X fflush(stdout); X } X hdrver = 2; /* note packing method */ X fseek(t, tloc, 0); /* reset output for new method */ X stdlen = crcval = 0; /* recalc these for kludge */ X while ((c = getch(f)) != EOF) /* store it straight */ X putc_pak(c, t); X hdr->crc = crcval; X hdr->length = hdr->size = stdlen; X } else if (ncrlen < lzwlen && ncrlen < huflen) { X if (note) { X printf("packing, "); /* pack with repeat */ X fflush(stdout); /* suppression */ X } X hdrver = 3; /* note packing method */ X hdr->size = ncrlen; /* set data length */ X fseek(t, tloc, 0); /* reset output for new method */ X while ((c = getc_ncr(f)) != EOF) X putc_pak(c, t); X } else if (huflen < lzwlen) { X if (note) { X printf("squeezing, "); X fflush(stdout); X } X hdrver = 4; /* note packing method */ X fseek(t, tloc, 0); /* reset output for new method */ X hdr->size = file_sq(f, t); /* note final size */ X } else { X if (note) X printf(dosquash ? "squashed, " : "crunched, "); X hdrver = dosquash ? 9 : 8; X hdr->size = lzwlen; /* size should not change */ X } X X /* standard cleanups common to all methods */ X X if (note) X printf("done. (%ld%%)\n",hdr->length == 0 ? X 0L : 100L - (100L*hdr->size)/hdr->length); X} X X/* X * Non-repeat compression - text is passed through normally, except that a X * run of more than two is encoded as: X * X * <char> <DLE> <count> X * X * Special case: a count of zero indicates that the DLE is really a DLE, not a X * repeat marker. X */ X Xint Xgetc_ncr(f) /* get bytes with collapsed runs */ X FILE *f; /* file to get from */ X{ X static int lastc; /* value returned on last call */ X static int repcnt; /* repetition counter */ X static int c; /* latest value seen */ X X switch (state) { /* depends on our state */ X case NOHIST: /* no relevant history */ X state = SENTCHAR; X return lastc = getch(f); /* remember the value next X * time */ X X case SENTCHAR: /* char was sent. look ahead */ X switch (lastc) {/* action depends on char */ X case DLE: /* if we sent a real DLE */ X state = NOHIST; /* then start over again */ X return 0; /* but note that the DLE was real */ X X case EOF: /* EOF is always a special case */ X return EOF; X X default: /* else test for a repeat */ X for (repcnt = 1; (c = getch(f)) == lastc && repcnt < 255; repcnt++); X /* find end of run */ X X switch (repcnt) { /* action depends on run size */ X case 1:/* not a repeat */ X return lastc = c; /* but remember value X * next time */ X X case 2:/* a repeat, but too short */ X state = SENDNEWC; /* send the second one X * next time */ X return lastc; X X default: /* a run - compress it */ X state = SENDCNT; /* send repeat count X * next time */ X return DLE; /* send repeat marker this X * time */ X } X } X X case SENDNEWC: /* send second char of short run */ X state = SENTCHAR; X return lastc = c; X X case SENDCNT: /* sent DLE, now send count */ X state = SENDNEWC; X return repcnt; X X default: X abort("Bug - bad ncr state\n"); X } X return 0; X} X Xint Xgetch(f) /* special get char for packing */ X FILE *f; /* file to get from */ X{ X int c; /* a char from the file */ X#if !DOS X static int cr = 0; /* add \r before \n ? */ X X if (cr) { X c = '\n'; X#if MTS X c = toascii(c); X#endif X crcval = addcrc(crcval, c); X stdlen++; X cr = 0; X return (c); X } X#endif X X if ((c = fgetc(f)) != EOF) { /* if not the end of file */ X#if !DOS X if (!image && (c == '\n')) { X c = '\r'; X cr = 1; X } X#endif X#if MTS X if (!image) X c = toascii(c); X#endif X crcval = addcrc(crcval, c); /* then update CRC check X * value */ X stdlen++; /* and bump length counter */ X } X return c; X} X Xvoid Xputc_pak(c, f) /* put a packed byte into archive */ X char c; /* byte to put */ X FILE *f; /* archive to put it in */ X{ X unsigned char code(); X putc_tst(code(c), f); /* put encoded byte, with checks */ X} SHAR_EOF if test 7438 -ne "`wc -c < 'arcpack.c'`" then echo shar: "error transmitting 'arcpack.c'" '(should have been 7438 characters)' fi fi echo shar: "extracting 'arcrun.c'" '(3859 characters)' if test -f 'arcrun.c' then echo shar: "will not over-write existing file 'arcrun.c'" else sed 's/^X//' << \SHAR_EOF > 'arcrun.c' X/* X * $Header: arcrun.c,v 1.4 88/07/31 18:52:50 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCRUN X * X * Version 1.20, created on 03/24/86 at 19:34:31 X * X * (C) COPYRIGHT 1985,85 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to "run" a file which is X * stored in an archive. At present, all we really do is (a) extract a X * temporary file, (b) give its name as a system command, and then (c) delete X * the file. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X Xvoid rempath(), openarc(), closearc(), abort(); Xint readhdr(), match(), unpack(); Xstatic void runfile(); Xchar *strcat(); X Xvoid Xrunarc(num, arg) /* run file from archive */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ X{ X struct heads hdr; /* file header */ X char *makefnam(); /* filename fixer */ X char buf[STRLEN]; /* filename buffer */ X FILE *fopen();/* file opener */ X char *dummy[2]; X X dummy[0]="dummy"; X dummy[1]=NULL; X rempath(num, arg); /* strip off paths */ X X openarc(0); /* open archive for reading */ X X if (num) { /* if files were named */ X while (readhdr(&hdr, arc)) { /* while more files to check */ X if (match(hdr.name, makefnam(arg[0], ".*", buf))) X runfile(&hdr, num, arg); X else X fseek(arc, hdr.size, 1); X } X } else X while (readhdr(&hdr, arc)) /* else run all files */ X runfile(&hdr, 1, dummy); X X closearc(0); /* close archive after changes */ X} X Xstatic void Xrunfile(hdr, num, arg) /* run a file */ X struct heads *hdr; /* pointer to header data */ X int num; /* number of arguments */ X char *arg[]; /* pointers to arguments */ X{ X FILE *tmp, *fopen(); /* temporary file */ X char *dir, *gcdir(); /* directory stuff */ X char buf[STRLEN], *makefnam(); /* temp file name, fixer */ X#if DOS X char nbuf[64], *i, *rindex(); X#endif X#if !GEMDOS X int n; /* index */ X char sys[STRLEN]; /* invocation command buffer */ X#endif X X /* makefnam("$ARCTEMP",hdr->name,buf); */ X#if UNIX X sprintf(buf, "%s.RUN", arctemp); X strcpy(sys, buf); X#else X strcpy(nbuf, arctemp); X makefnam(nbuf,hdr->name,buf); X i = rindex(buf,'.'); X#endif X#if MSDOS X if (!strcmp(i, ".BAS")) { X strcpy(sys, "BASICA "); X strcat(sys, buf); X } X else if (!strcmp(i, ".BAT") X || !strcmp(i, ".COM") X || !strcmp(i, ".EXE")) X strcpy(sys, buf); X X else { X if (warn) { X printf("File %s is not a .BAS, .BAT, .COM, or .EXE\n", X hdr->name); X nerrs++; X } X fseek(arc, hdr->size, 1); /* skip this file */ X return; X } X#endif X#if GEMDOS X if (strcmp(i, ".PRG") X && strcmp(i, ".TTP") X && strcmp(i, ".TOS")) X { X if (warn) { X printf("File %s is not a .PRG, .TOS, or .TTP\n", X hdr->name); X nerrs++; X } X fseek(arc, hdr->size, 1); /* skip this file */ X return; X } X#endif X X if (warn) X if (tmp = fopen(buf, "r")) X abort("Temporary file %s already exists", buf); X if (!(tmp = fopen(buf, OPEN_W))) X abort("Unable to create temporary file %s", buf); X X if (note) X printf("Invoking file: %s\n", hdr->name); X X dir = gcdir(""); /* see where we are */ X unpack(arc, tmp, hdr); /* unpack the entry */ X fclose(tmp); /* release the file */ X chmod(buf, "700"); /* make it executable */ X#if GEMDOS X execve(buf, arg, NULL); X#else X for (n = 1; n < num; n++) { /* add command line arguments */ X strcat(sys, " "); X strcat(sys, arg[n]); X } X system(buf); /* try to invoke it */ X#endif X chdir(dir); X free(dir); /* return to whence we started */ X if (unlink(buf) && warn) { X printf("Cannot unsave temporary file %s\n", buf); X nerrs++; X } X} SHAR_EOF if test 3859 -ne "`wc -c < 'arcrun.c'`" then echo shar: "error transmitting 'arcrun.c'" '(should have been 3859 characters)' fi fi echo shar: "extracting 'arcs.h'" '(1645 characters)' if test -f 'arcs.h' then echo shar: "will not over-write existing file 'arcs.h'" else sed 's/^X//' << \SHAR_EOF > 'arcs.h' X/* X * $Header: arcs.h,v 1.2 88/04/17 18:53:19 hyc Exp $ X */ X X/* X * ARC - Archive utility - Archive file header format X * X * Version 2.12, created on 12/17/85 at 14:40:26 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file defines the format of an archive file header, X * excluding the archive marker and the header version number. X * X * Each entry in an archive begins with a one byte archive marker, which is set X * to 26. The marker is followed by a one byte header type code, from zero X * to 7. X * X * If the header type code is zero, then it is an end marker, and no more data X * should be read from the archive. X * X * If the header type code is in the range 2 to 7, then it is followed by a X * standard archive header, which is defined below. X * X * If the header type code is one, then it is followed by an older format X * archive header. The older format header does not contain the true length. X * A header should be read for a length of sizeof(struct heads)-sizeof(long). X * Then set length equal to size and change the header version to 2. X * X * Programming note: The crc value given in the header is based on the unpacked X * data. X * X * Language: Computer Innovations Optimizing C86 X */ X Xstruct heads { /* archive entry header format */ X char name[FNLEN]; /* file name */ X long size; /* size of file, in bytes */ X unsigned short date; /* creation date */ X unsigned short time; /* creation time */ X short crc; /* cyclic redundancy check */ X long length; /* true file length */ X}; SHAR_EOF if test 1645 -ne "`wc -c < 'arcs.h'`" then echo shar: "error transmitting 'arcs.h'" '(should have been 1645 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (01/03/89)
This is part 6 (of 6) to the Arc v5.21 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # marc.c # memset.c # rename.c # scandir.3 # scandir.c # tmclock.c # utimes.c # This archive created: Sun Jan 1 12:48:37 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'marc.c'" '(9440 characters)' if test -f 'marc.c' then echo shar: "will not over-write existing file 'marc.c'" else sed 's/^X//' << \SHAR_EOF > 'marc.c' X/* X * $Header: marc.c,v 1.5 88/08/01 14:19:19 hyc Exp $ X */ X X/* MARC - Archive merge utility X X Version 5.21, created on 04/22/87 at 15:05:10 X X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This program is used to "merge" archives. That is, to move X files from one archive to another with no data conversion. X Please refer to the ARC source for a description of archives X and archive formats. X X Instructions: X Run this program with no arguments for complete instructions. X X Language: X Computer Innovations Optimizing C86 X*/ X#include <stdio.h> X#include "arc.h" X X#if UNIX X#include <sys/types.h> X#include <sys/stat.h> X#endif X XFILE *src; /* source archive */ Xchar srcname[STRLEN]; /* source archive name */ X Xstatic char **lst; /* files list */ Xstatic int lnum; /* length of files list */ X X#ifdef LOCAL Xint unix_names = 0; X#endif /* LOCAL */ X X Xmain(nargs,arg) /* system entry point */ Xint nargs; /* number of arguments */ Xchar *arg[]; /* pointers to arguments */ X{ X char *makefnam(); /* filename fixup routine */ X char *calloc(); /* memory manager */ X char *envfind(); X#if !MTS X char *arctemp2, *mktemp(); /* temp file stuff */ X#endif X#if GEMDOS X void exitpause(); X#endif X int n; /* index */ X#if UNIX X struct stat sbuf; X#endif X X X if(nargs<3) X { printf("MARC - Archive merger, Version 5.21, created on 04/22/87 at 15:05:10\n"); X/* printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;"); X printf(" ALL RIGHTS RESERVED\n\n"); X printf("Please refer all inquiries to:\n\n"); X printf(" System Enhancement Associates\n"); X printf(" 21 New Street, Wayne NJ 07470\n\n"); X printf("You may copy and distribute this program freely,"); X printf(" provided that:\n"); X printf(" 1) No fee is charged for such copying and"); X printf(" distribution, and\n"); X printf(" 2) It is distributed ONLY in its original,"); X printf(" unmodified state.\n\n"); X printf("If you like this program, and find it of use, then your"); X printf(" contribution will\n"); X printf("be appreciated. You may not use this product in a"); X printf(" commercial environment\n"); X printf("or a governmental organization without paying a license"); X printf(" fee of $35. Site\n"); X printf("licenses and commercial distribution licenses are"); X printf(" available. A program\n"); X printf("disk and printed documentation are available for $50.\n"); X printf("\nIf you fail to abide by the terms of this license, "); X printf(" then your conscience\n"); X printf("will haunt you for the rest of your life.\n\n"); X*/ X printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n"); X printf("Where: <tgtarc> is the archive to add files to,\n"); X printf(" <srcarc> is the archive to get files from, and\n"); X printf(" <filename> is zero or more file names to get.\n"); X printf("\nAdapted from MSDOS by Howard Chu\n"); X#if GEMDOS X exitpause(); X#endif X return 1; X } X X /* see where temp files go */ X#if !MTS X arctemp = calloc(1, STRLEN); X if (!(arctemp2 = envfind("ARCTEMP"))) X arctemp2 = envfind("TMPDIR"); X if (arctemp2) { X strcpy(arctemp, arctemp2); X n = strlen(arctemp); X if (arctemp[n - 1] != CUTOFF) X arctemp[n] = CUTOFF; X } X#if UNIX X else strcpy(arctemp, "/tmp/"); X#endif X#if !MSDOS X { X static char tempname[] = "AXXXXXX"; X strcat(arctemp, mktemp(tempname)); X } X#else X strcat(arctemp, "$ARCTEMP"); X#endif X#else X guinfo("SHFSEP ", gotinf); X sepchr[0] = gotinf[0]; X guinfo("SCRFCHAR", gotinf); X tmpchr[0] = gotinf[0]; X arctemp = "-$$$"; X arctemp[0] = tmpchr[0]; X#endif X X#if UNIX X if (!stat(arg[1],&sbuf)) X strcpy(arcname,arg[1]); X else X makefnam(arg[1],".arc",arcname); X if (!stat(arg[2],&sbuf)) X strcpy(srcname,arg[2]); X else X makefnam(arg[2],".arc",srcname); X#else X makefnam(arg[1],".ARC",arcname); /* fix up archive names */ X makefnam(arg[2],".ARC",srcname); X/* makefnam(".$$$",arcname,newname);*/ X sprintf(newname,"%s.arc",arctemp); X#endif X X arc = fopen(arcname,OPEN_R); /* open the archives */ X if(!(src=fopen(srcname,OPEN_R))) X abort("Cannot read source archive %s",srcname); X if(!(new=fopen(newname,OPEN_W))) X abort("Cannot create new archive %s",newname); X X if(!arc) X printf("Creating new archive %s\n",arcname); X X /* get the files list set up */ X X lnum = nargs-3; /* initial length of list */ X if(lnum<1) /* phoney for default case */ X { lnum = 1; X lst = (char **) calloc(1,sizeof(char *)); X lst[0] = "*.*"; X } X else /* else use filenames given */ X { lst = (char **) calloc(lnum,sizeof(char *)); X for(n=3; n<nargs; n++) X lst[n-3] = arg[n]; X X for(n=0; n<lnum; ) /* expand indirect references */ X { if(*lst[n] == '@') X expandlst(n); X else n++; X } X } X X merge(lnum,lst); /* merge desired files */ X X if(arc) fclose(arc); /* close the archives */ X fclose(src); X fclose(new); X X if(arc) /* make the switch */ X if(unlink(arcname)) X abort("Unable to delete old copy of %s",arcname); X if(move(newname,arcname)) X abort("Unable to rename %s to %s",newname,arcname); X X setstamp(arcname,arcdate,arctime); /* new arc matches newest file */ X X#if GEMDOS X exitpause(); X#endif X return nerrs; X} X Xmerge(nargs,arg) /* merge two archives */ Xint nargs; /* number of filename templates */ Xchar *arg[]; /* pointers to names */ X{ X struct heads srch; /* source archive header */ X struct heads arch; /* target archive header */ X int gotsrc, gotarc; /* archive entry versions (0=end) */ X int copy; /* true to copy file from source */ X int n; /* index */ X X gotsrc = gethdr(src,&srch); /* get first source file */ X gotarc = gethdr(arc,&arch); /* get first target file */ X X while(gotsrc || gotarc) /* while more to merge */ X { if(strcmp(srch.name,arch.name)>0) X { copyfile(arc,&arch,gotarc); X gotarc = gethdr(arc,&arch); X } X X else if(strcmp(srch.name,arch.name)<0) X { copy = 0; X for(n=0; n<nargs; n++) X { if(match(srch.name,arg[n])) X { copy = 1; X break; X } X } X if(copy) /* select source or target */ X { printf("Adding file: %s\n",srch.name); X copyfile(src,&srch,gotsrc); X } X else fseek(src,srch.size,1); X gotsrc = gethdr(src,&srch); X } X X else /* duplicate names */ X { copy = 0; X { if((srch.date>arch.date) X || (srch.date==arch.date && srch.time>arch.time)) X { for(n=0; n<nargs; n++) X { if(match(srch.name,arg[n])) X { copy = 1; X break; X } X } X } X } X if(copy) /* select source or target */ X { printf("Updating file: %s\n",srch.name); X copyfile(src,&srch,gotsrc); X gotsrc = gethdr(src,&srch); X if(gotarc) X { fseek(arc,arch.size,1); X gotarc = gethdr(arc,&arch); X } X } X else X { copyfile(arc,&arch,gotarc); X gotarc = gethdr(arc,&arch); X if(gotsrc) X { fseek(src,srch.size,1); X gotsrc = gethdr(src,&srch); X } X } X } X } X X hdrver = 0; /* end of archive marker */ X writehdr(&arch,new); /* mark the end of the archive */ X} X Xint gethdr(f,hdr) /* special read header for merge */ XFILE *f; /* file to read from */ Xstruct heads *hdr; /* storage for header */ X{ X char *i = hdr->name; /* string index */ X int n; /* index */ X X for(n=0; n<FNLEN; n++) /* fill name field */ X *i++ = 0176; /* impossible high value */ X *--i = '\0'; /* properly end the name */ X X hdrver = 0; /* reset header version */ X if(readhdr(hdr,f)) /* use normal reading logic */ X return hdrver; /* return the version */ X else return 0; /* or fake end of archive */ X} X Xcopyfile(f,hdr,ver) /* copy a file from an archive */ XFILE *f; /* archive to copy from */ Xstruct heads *hdr; /* header data for file */ Xint ver; /* header version */ X{ X hdrver = ver; /* set header version */ X writehdr(hdr,new); /* write out the header */ X filecopy(f,new,hdr->size); /* copy over the data */ X} X Xstatic expandlst(n) /* expand an indirect reference */ Xint n; /* number of entry to expand */ X{ X FILE *lf, *fopen(); /* list file, opener */ X char *malloc(), *realloc(); /* memory managers */ X char buf[100]; /* input buffer */ X int x; /* index */ X char *p = lst[n]+1; /* filename pointer */ X X if(*p) /* use name if one was given */ X { makefnam(p,".CMD",buf); X upper(buf); X if(!(lf=fopen(buf,"r"))) X abort("Cannot read list of files in %s",buf); X } X else lf = stdin; /* else use standard input */ X X for(x=n+1; x<lnum; x++) /* drop reference from the list */ X lst[x-1] = lst[x]; X lnum--; X X while(fscanf(lf,"%99s",buf)>0) /* read in the list */ X { if(!(lst=(char **) realloc(lst,(lnum+1)*sizeof(char *)))) X abort("too many file references"); X X lst[lnum] = malloc(strlen(buf)+1); X strcpy(lst[lnum],buf); /* save the name */ X lnum++; X } X X if(lf!=stdin) /* avoid closing standard input */ X fclose(lf); X} SHAR_EOF if test 9440 -ne "`wc -c < 'marc.c'`" then echo shar: "error transmitting 'marc.c'" '(should have been 9440 characters)' fi fi echo shar: "extracting 'memset.c'" '(144 characters)' if test -f 'memset.c' then echo shar: "will not over-write existing file 'memset.c'" else sed 's/^X//' << \SHAR_EOF > 'memset.c' X/* missing function X */ Xchar * Xmemset(d, n, c) X char *d; X int n; X char c; X{ X char *s = d; X X while (n > 0) { X --n; X *d++ = c; X } X return(s); X} SHAR_EOF if test 144 -ne "`wc -c < 'memset.c'`" then echo shar: "error transmitting 'memset.c'" '(should have been 144 characters)' fi fi echo shar: "extracting 'rename.c'" '(280 characters)' if test -f 'rename.c' then echo shar: "will not over-write existing file 'rename.c'" else sed 's/^X//' << \SHAR_EOF > 'rename.c' X/* X * substitute for BSD/SVR3 rename() system call, from X * Janet Walz, walz@mimsy.umd.edu & Rich Salz, rsalz@pineapple.bbn.com X */ X Xint rename(oldname,newname) Xchar *oldname,*newname; X{ X (void)unlink(newname); X if(link(oldname,newname)) X return(-1); X return(unlink(oldname)); X} SHAR_EOF if test 280 -ne "`wc -c < 'rename.c'`" then echo shar: "error transmitting 'rename.c'" '(should have been 280 characters)' fi fi echo shar: "extracting 'scandir.3'" '(2353 characters)' if test -f 'scandir.3' then echo shar: "will not over-write existing file 'scandir.3'" else sed 's/^X//' << \SHAR_EOF > 'scandir.3' X.TH SCANDIR 3 X.\" $Header: scandir.3,v 1.1 87/12/29 21:35:54 rsalz Exp $ X.SH NAME Xscandir, alphasort \- scan a directory X.SH SYNOPSIS X.nf X.ft B X#include <sys/types.h> X#include <sys/dirent.h> X Xint Xscandir(name, list, selector, sorter) X.in +4n Xchar *name; Xstruct dirent ***list; Xint (*selector)(); Xint (*sorter)(); X.in -4n X Xint Xalphasort(d1, d2) X.in +4n Xstruct dirent **d1; Xstruct dirent **d2; X.in -4n X.ft R X.fi X.SH DESCRIPTION X.I Scandir Xreads the directory X.I name Xand builds a NULL\-terminated array of pointers to the entries found Xin that directory. XThis array is put into the location pointed to by the X.I list Xparameter. X.PP XIf the X.I selector Xparameter is non\-NULL, it is taken to be a pointer to a function called Xwith each entry, to determine whether or not it should be included in Xthe returned list. XIf the parameter is NULL, all entries are included. X.PP XAs an added feature, the entries can be sorted (with X.IR qsort (3)) Xbefore the list is returned. XIf the X.I sorter Xparameter is non\-NULL, it is passed to qsort to use as the comparison Xfunction. XThe X.I alphasort Xroutine is provided to sort the array alphabetically. X.PP XThe array pointed to by X.I list Xand the items it points to are all space obtained through X.IR malloc (3), Xand their storage can be reclaimed as shown in the example below. X.SH "EXAMPLE" XHere is a small X.IR ls (1)\-like Xprogram: X.ne 50 X.RS X.nf X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/dir.h> X Xextern int alphasort(); X Xstatic int Xfilesonly(e) X struct dirent *e; X{ X struct stat sb; X X return(stat(e->d_name, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG); X} X Xmain(ac, av) X int ac; X char *av[]; X{ X register int i; X register int j; X struct dirent **list; X X if (ac != 2) { X fprintf(stderr, "usage: %s dirname\n", av[0]); X exit(1); X } X if (chdir(av[1]) < 0) { X perror(av[1]); X exit(1); X } X if ((i = scandir(".", &list, filesonly, alphasort)) < 0) { X perror("Error reading directory"); X exit(1); X } X for (j = 0; j < i; j++) X printf("%s\n", list[j]->d_name); X for (j = 0; j < i; j++) X free((char *)list[j]); X free((char *)list); X exit(0); X} X.fi X.RE X.SH "SEE ALSO" Xdirectory(3), qsort(3) X.SH DIAGNOSTICS XReturns the number of entries in the ``list,'' or \-1 if the directory Xcould not be opened or a memory allocation failed. X.SH BUGS XThe routine can be slightly wasteful of space. SHAR_EOF if test 2353 -ne "`wc -c < 'scandir.3'`" then echo shar: "error transmitting 'scandir.3'" '(should have been 2353 characters)' fi fi echo shar: "extracting 'scandir.c'" '(2409 characters)' if test -f 'scandir.c' then echo shar: "will not over-write existing file 'scandir.c'" else sed 's/^X//' << \SHAR_EOF > 'scandir.c' X/* X** SCANDIR X** Scan a directory, collecting all (selected) items into a an array. X*/ X X#ifdef RCSID Xstatic char RCS[] = "$Header: scandir.c,v 1.1 87/12/29 21:35:56 rsalz Exp $"; X#endif /* RCSID */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/dir.h> X X#ifdef MAXNAMLEN X X#include <dirent.h> X#define namedir(entry) (entry->d_name) X#define MAXNAME 256 X X#else X X#define dirent direct X#define DIR FILE X#define MAXNAME (DIRSIZ+2) X#define opendir(path) fopen (path, "r") X#define closedir(dirp) fclose (dirp) Xstruct direct * Xreaddir (dirp) XDIR *dirp; X { X static struct direct entry; X if (dirp == NULL) return (NULL); X for (;;) X { X if (fread (&entry, sizeof (struct direct), 1, dirp) == 0) return (NULL); X if (entry.d_ino) return (&entry); X } X } X#endif X X/* Initial guess at directory size. */ X#define INITIAL_SIZE 20 X X/* A convenient shorthand. */ Xtypedef struct dirent ENTRY; X X#define MDIRSIZ(d) (sizeof(struct dirent) + strlen(d->d_name) + 1) X X/* Linked in later. */ Xextern char *malloc(); Xextern char *realloc(); Xextern char *strcpy(); X X Xint Xscandir(Name, List, Selector, Sorter) X char *Name; X ENTRY ***List; X int (*Selector)(); X int (*Sorter)(); X{ X register ENTRY **names; X register ENTRY *E; X register DIR *Dp; X register int i; X register int size; X X /* Get initial list space and open directory. */ X size = INITIAL_SIZE; X if ((names = (ENTRY **)malloc(size * sizeof names[0])) == NULL X || (Dp = opendir(Name)) == NULL) X return(-1); X X /* Read entries in the directory. */ X for (i = 0; E = readdir(Dp); ) X if (Selector == NULL || (*Selector)(E)) { X /* User wants them all, or he wants this one. */ X if (++i >= size) { X size <<= 1; X names = (ENTRY **)realloc((char *)names, size * sizeof names[0]); X if (names == NULL) { X closedir(Dp); X return(-1); X } X } X X /* Copy the entry. */ X if ((names[i - 1] = (ENTRY *)malloc(MDIRSIZ(E))) == NULL) { X closedir(Dp); X return(-1); X } X names[i - 1]->d_ino = E->d_ino; X#ifndef SYSV X names[i - 1]->d_reclen = E->d_reclen; X /* names[i - 1]->d_namlen = E->d_namlen; */ X#endif /* SYSV */ X (void)strcpy(names[i - 1]->d_name, E->d_name); X } X X /* Close things off. */ X names[i] = NULL; X *List = names; X closedir(Dp); X X /* Sort? */ X if (i && Sorter) X qsort((char *)names, i, sizeof names[0], Sorter); X X return(i); X} SHAR_EOF if test 2409 -ne "`wc -c < 'scandir.c'`" then echo shar: "error transmitting 'scandir.c'" '(should have been 2409 characters)' fi fi echo shar: "extracting 'tmclock.c'" '(2334 characters)' if test -f 'tmclock.c' then echo shar: "will not over-write existing file 'tmclock.c'" else sed 's/^X//' << \SHAR_EOF > 'tmclock.c' X/* X * Stolen from Jef Poskanzer's tws time library, which was stolen from X * Marshall Rose's MH Message Handling system... X * X * tmclock() will convert time from a tm struct back to a clock value. X * tmjuliandate() converts a tm struct to its julian day number. X * tmsubdayclock() takes hours, minutes, and seconds from a tm struct X * and returns the number of seconds since midnight of that day. (?) X * -- Howard Chu, August 1 1988 hyc@umix.cc.umich.edu, umix!hyc X */ X X/* $Header: tmclock.c,v 1.3 88/08/02 14:15:58 hyc Exp $ */ X X/* Julian day number of the Unix* clock's origin, 01 Jan 1970. */ X#define JD1970 2440587L X#define CENTURY 19 X#if BSD X#include <sys/time.h> Xint daylight; X#else X#include <time.h> X#endif X Xlong tzone; X Xlong Xtmjuliandate( tm ) Xstruct tm *tm; X { X register int mday, mon, year; X register long a, b; X double jd; X X if ( (mday = tm -> tm_mday) < 1 || mday > 31 || X (mon = tm -> tm_mon + 1) < 1 || mon > 12 || X (year = tm -> tm_year) < 1 || year > 10000 ) X return ( -1L ); X if ( year < 100 ) X year += CENTURY * 100; X X if ( mon == 1 || mon == 2 ) X { X --year; X mon += 12; X } X if ( year < 1583 ) X return ( -1L ); X a = year / 100; X b = 2 - a + a / 4; X b += (long) ( (double) year * 365.25 ); X b += (long) ( 30.6001 * ( (double) mon + 1.0 ) ); X jd = mday + b + 1720994.5; X return ( (long) jd ); X } X X Xlong Xtmsubdayclock( tm ) Xstruct tm *tm; X { X register int sec, min, hour; X register long result; X#if BSD X { X struct timeval tp; X struct timezone tzp; X X gettimeofday(&tp, &tzp); X daylight=tzp.tz_dsttime; X tzone=tzp.tz_minuteswest*(-60); X } X#else X tzset(); X tzone = -timezone; /* declared as extern in SYSV <time.h> */ X#endif X if ( (sec = tm -> tm_sec) < 0 || sec > 59 || X (min = tm -> tm_min) < 0 || min > 59 || X (hour = tm -> tm_hour) < 0 || hour > 23 ) X return ( -1L ); X X result = ( hour * 60 + min ) * 60 + sec; X result -= tzone; X if ( tm->tm_isdst ) X result -= 60 * 60; X X return ( result ); X } X X Xlong Xtmclock( tm ) Xstruct tm *tm; X { X register long jd, sdc, result; X X if ( ( jd = tmjuliandate( tm ) ) == -1L ) X return ( -1L ); X if ( ( sdc = tmsubdayclock( tm ) ) == -1L ) X return ( -1L ); X X result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc; X X return ( result ); X } SHAR_EOF if test 2334 -ne "`wc -c < 'tmclock.c'`" then echo shar: "error transmitting 'tmclock.c'" '(should have been 2334 characters)' fi fi echo shar: "extracting 'utimes.c'" '(399 characters)' if test -f 'utimes.c' then echo shar: "will not over-write existing file 'utimes.c'" else sed 's/^X//' << \SHAR_EOF > 'utimes.c' X X/* bsd utimes emulation for Sys V */ X/* by Jon Zeeff */ X X#include <sys/types.h> X Xstruct utimbuf { X time_t actime; X time_t modtime; X}; X Xstruct timeval { X long tv_sec; X long tv_usec; X}; X Xutimes(path,tvp) Xchar *path; Xstruct timeval tvp[2]; X{ X Xstruct utimbuf times; X Xtimes.actime = (time_t) tvp[0].tv_sec; Xtimes.modtime = (time_t) tvp[1].tv_sec; X Xreturn utime(path, ×); X X} SHAR_EOF if test 399 -ne "`wc -c < 'utimes.c'`" then echo shar: "error transmitting 'utimes.c'" '(should have been 399 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (01/03/89)
This is part 5 (of 6) to the Arc v5.21 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # arcsq.c # arcsqs.c # arcsvc.c # arctst.c # arcunp.c # arcusq.c # getwd.c # This archive created: Sun Jan 1 12:48:31 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'arcsq.c'" '(14548 characters)' if test -f 'arcsq.c' then echo shar: "will not over-write existing file 'arcsq.c'" else sed 's/^X//' << \SHAR_EOF > 'arcsq.c' X/* X * $Header: arcsq.c,v 1.3 88/07/31 18:53:32 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCSQ X * X * Version 3.10, created on 01/30/86 at 20:10:46 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to squeeze a file when X * placing it in an archive. X * X * Language: Computer Innovations Optimizing C86 X * X * Programming notes: Most of the routines used for the Huffman squeezing X * algorithm were lifted from the SQ program by Dick Greenlaw, as adapted to X * CI-C86 by Robert J. Beilstein. X */ X#include <stdio.h> X#include "arc.h" X X/* stuff for Huffman squeezing */ X X#define TRUE 1 X#define FALSE 0 X#define ERROR (-1) X#define SPEOF 256 /* special endfile token */ X#define NOCHILD (-1) /* marks end of path through tree */ X#define NUMVALS 257 /* 256 data values plus SPEOF */ X#define NUMNODES (NUMVALS+NUMVALS-1) /* number of nodes */ X#define MAXCOUNT (unsigned short) 65535 /* biggest unsigned integer */ X X/* X * The following array of structures are the nodes of the binary trees. The X * first NUMVALS nodes become the leaves of the final tree and represent the X * values of the data bytes being encoded and the special endfile, SPEOF. The X * remaining nodes become the internal nodes of the final tree. X */ X Xstruct nd { /* shared by unsqueezer */ X unsigned short weight; /* number of appearances */ X short tdepth; /* length on longest path in tree */ X short lchild, rchild; /* indices to next level */ X} node[NUMNODES]; /* use large buffer */ X Xstatic int dctreehd; /* index to head of final tree */ X X/* X * This is the encoding table: The bit strings have first bit in low bit. X * Note that counts were scaled so code fits unsigned integer. X */ X Xstatic int codelen[NUMVALS]; /* number of bits in code */ Xstatic unsigned short code[NUMVALS]; /* code itself, right adjusted */ Xstatic unsigned short tcode; /* temporary code value */ Xstatic long valcount[NUMVALS]; /* actual count of times seen */ X X/* Variables used by encoding process */ X Xstatic int curin; /* value currently being encoded */ Xstatic int cbitsrem; /* # of code string bits left */ Xstatic unsigned short ccode; /* current code right justified */ X Xstatic void scale(), heap(), adjust(), bld_tree(), init_enc(), put_int(); Xstatic int cmptrees(), buildenc(), maxchar(); Xvoid Xinit_sq() X{ /* prepare for scanning pass */ X int i; /* node index */ X X /* X * Initialize all nodes to single element binary trees with zero X * weight and depth. X */ X X for (i = 0; i < NUMNODES; ++i) { X node[i].weight = 0; X node[i].tdepth = 0; X node[i].lchild = NOCHILD; X node[i].rchild = NOCHILD; X } X X for (i = 0; i < NUMVALS; i++) X valcount[i] = 0; X} X Xvoid Xscan_sq(c) /* add a byte to the tables */ X int c; /* byte to add */ X{ X unsigned short *wp; /* speeds up weight counting */ X X /* Build frequency info in tree */ X X if (c == EOF) /* it's traditional */ X c = SPEOF; /* dumb, but traditional */ X X if (*(wp = &node[c].weight) != MAXCOUNT) X ++(*wp); /* bump weight counter */ X X valcount[c]++; /* bump byte counter */ X} X Xlong Xpred_sq() X{ /* predict size of squeezed file */ X int i; X int btlist[NUMVALS]; /* list of intermediate X * b-trees */ X int listlen;/* length of btlist */ X unsigned short ceiling;/* limit for scaling */ X long size = 0; /* predicted size */ X int numnodes; /* # of nodes in simplified tree */ X X scan_sq(EOF); /* signal end of input */ X X ceiling = MAXCOUNT; X X /* Keep trying to scale and encode */ X X do { X scale(ceiling); X ceiling /= 2; /* in case we rescale */ X X /* X * Build list of single node binary trees having leaves for X * the input values with non-zero counts X */ X X for (i = listlen = 0; i < NUMVALS; ++i) { X if (node[i].weight != 0) { X node[i].tdepth = 0; X btlist[listlen++] = i; X } X } X X /* X * Arrange list of trees into a heap with the entry indexing X * the node with the least weight at the top. X */ X X heap(btlist, listlen); X X /* Convert the list of trees to a single decoding tree */ X X bld_tree(btlist, listlen); X X /* Initialize the encoding table */ X X init_enc(); X X /* X * Try to build encoding table. Fail if any code is > 16 bits X * long. X */ X } while (buildenc(0, dctreehd) == ERROR); X X /* Initialize encoding variables */ X X cbitsrem = 0; /* force initial read */ X curin = 0; /* anything but endfile */ X X for (i = 0; i < NUMVALS; i++) /* add bits for each code */ X size += valcount[i] * codelen[i]; X X size = (size + 7) / 8; /* reduce to number of bytes */ X X numnodes = dctreehd < NUMVALS ? 0 : dctreehd - (NUMVALS - 1); X X size += sizeof(short) + 2 * numnodes * sizeof(short); X X return size; X} X X/* X * The count of number of occurrances of each input value have already been X * prevented from exceeding MAXCOUNT. Now we must scale them so that their X * sum doesn't exceed ceiling and yet no non-zero count can become zero. This X * scaling prevents errors in the weights of the interior nodes of the X * Huffman tree and also ensures that the codes will fit in an unsigned X * integer. Rescaling is used if necessary to limit the code length. X */ X Xstatic void Xscale(ceil) X unsigned short ceil; /* upper limit on total weight */ X{ X register int i; X int ovflw, divisor; X unsigned short w, sum; X unsigned char increased; /* flag */ X X do { X for (i = sum = ovflw = 0; i < NUMVALS; ++i) { X if (node[i].weight > (ceil - sum)) X ++ovflw; X sum += node[i].weight; X } X X divisor = ovflw + 1; X X /* Ensure no non-zero values are lost */ X X increased = FALSE; X for (i = 0; i < NUMVALS; ++i) { X w = node[i].weight; X if (w < divisor && w != 0) { /* Don't fail to provide X * a code if it's used X * at all */ X X node[i].weight = divisor; X increased = TRUE; X } X } X } while (increased); X X /* Scaling factor chosen, now scale */ X X if (divisor > 1) X for (i = 0; i < NUMVALS; ++i) X node[i].weight /= divisor; X} X X/* X * heap() and adjust() maintain a list of binary trees as a heap with the top X * indexing the binary tree on the list which has the least weight or, in X * case of equal weights, least depth in its longest path. The depth part is X * not strictly necessary, but tends to avoid long codes which might provoke X * rescaling. X */ X Xstatic void Xheap(list, length) X int list[], length; X{ X register int i; X X for (i = (length - 2) / 2; i >= 0; --i) X adjust(list, i, length - 1); X} X X/* Make a heap from a heap with a new top */ X Xstatic void Xadjust(list, top, bottom) X int list[], top, bottom; X{ X register int k, temp; X X k = 2 * top + 1; /* left child of top */ X temp = list[top]; /* remember root node of top tree */ X X if (k <= bottom) { X if (k < bottom && cmptrees(list[k], list[k + 1])) X ++k; X X /* k indexes "smaller" child (in heap of trees) of top */ X /* now make top index "smaller" of old top and smallest child */ X X if (cmptrees(temp, list[k])) { X list[top] = list[k]; X list[k] = temp; X X /* Make the changed list a heap */ X X adjust(list, k, bottom); /* recursive */ X } X } X} X X/* X * Compare two trees, if a > b return true, else return false. Note X * comparison rules in previous comments. X */ X Xstatic int Xcmptrees(a, b) X int a, b; /* root nodes of trees */ X{ X if (node[a].weight > node[b].weight) X return TRUE; X if (node[a].weight == node[b].weight) X if (node[a].tdepth > node[b].tdepth) X return TRUE; X return FALSE; X} X X/* X * HUFFMAN ALGORITHM: develops the single element trees into a single binary X * tree by forming subtrees rooted in interior nodes having weights equal to X * the sum of weights of all their descendents and having depth counts X * indicating the depth of their longest paths. X * X * When all trees have been formed into a single tree satisfying the heap X * property (on weight, with depth as a tie breaker) then the binary code X * assigned to a leaf (value to be encoded) is then the series of left (0) X * and right (1) paths leading from the root to the leaf. Note that trees are X * removed from the heaped list by moving the last element over the top X * element and reheaping the shorter list. X */ X Xstatic void Xbld_tree(list, len) X int list[]; Xint len; X{ X register int freenode; /* next free node in tree */ X register struct nd *frnp; /* free node pointer */ X int lch, rch; /* temps for left, right children */ X X /* X * Initialize index to next available (non-leaf) node. Lower numbered X * nodes correspond to leaves (data values). X */ X X freenode = NUMVALS; X X while (len > 1) { /* Take from list two btrees with least X * weight and build an interior node pointing X * to them. This forms a new tree. */ X X lch = list[0]; /* This one will be left child */ X X /* delete top (least) tree from the list of trees */ X X list[0] = list[--len]; X adjust(list, 0, len - 1); X X /* Take new top (least) tree. Reuse list slot later */ X X rch = list[0]; /* This one will be right child */ X X /* X * Form new tree from the two least trees using a free node X * as root. Put the new tree in the list. X */ X X frnp = &node[freenode]; /* address of next free node */ X list[0] = freenode++; /* put at top for now */ X frnp->lchild = lch; X frnp->rchild = rch; X frnp->weight = node[lch].weight + node[rch].weight; X frnp->tdepth = 1 + maxchar(node[lch].tdepth, node[rch].tdepth); X X /* reheap list to get least tree at top */ X X adjust(list, 0, len - 1); X } X dctreehd = list[0]; /* head of final tree */ X} X Xstatic int Xmaxchar(a, b) X{ X return a > b ? a : b; X} X Xstatic void Xinit_enc() X{ X register int i; X X /* Initialize encoding table */ X X for (i = 0; i < NUMVALS; ++i) X codelen[i] = 0; X} X X/* X * Recursive routine to walk the indicated subtree and level and maintain the X * current path code in bstree. When a leaf is found the entire code string X * and length are put into the encoding table entry for the leaf's data value X * . X * X * Returns ERROR if codes are too long. X */ X Xstatic int Xbuildenc(level, root) X int level; /* level of tree being examined, from zero */ X int root; /* root of subtree is also data value if leaf */ X{ X register int l, r; X X l = node[root].lchild; X r = node[root].rchild; X X if (l == NOCHILD && r == NOCHILD) { /* Leaf. Previous path X * determines bit string code X * of length level (bits 0 to X * level - 1). Ensures unused X * code bits are zero. */ X X codelen[root] = level; X code[root] = tcode & (((unsigned short ) ~0) >> (16 - level)); X return (level > 16) ? ERROR : 0; X } else { X if (l != NOCHILD) { /* Clear path bit and continue deeper */ X X tcode &= ~(1 << level); X if (buildenc(level + 1, l) == ERROR) X return ERROR; /* pass back bad statuses */ X } X if (r != NOCHILD) { /* Set path bit and continue deeper */ X X tcode |= 1 << level; X if (buildenc(level + 1, r) == ERROR) X return ERROR; /* pass back bad statuses */ X } X } X return NULL; /* it worked if we reach here */ X} X Xstatic void Xput_int(n, f) /* output an integer */ X short n; /* integer to output */ X FILE *f; /* file to put it to */ X{ X void putc_pak(); X X putc_pak(n & 0xff, f); /* first the low byte */ X putc_pak(n >> 8, f); /* then the high byte */ X} X X/* Write out the header of the compressed file */ X Xstatic long Xwrt_head(ob) X FILE *ob; X{ X register int l, r; X int i, k; X int numnodes; /* # of nodes in simplified tree */ X X /* X * Write out a simplified decoding tree. Only the interior nodes are X * written. When a child is a leaf index (representing a data value) X * it is recoded as -(index + 1) to distinguish it from interior X * indexes which are recoded as positive indexes in the new tree. X * X * Note that this tree will be empty for an empty file. X */ X X numnodes = dctreehd < NUMVALS ? 0 : dctreehd - (NUMVALS - 1); X put_int(numnodes, ob); X X for (k = 0, i = dctreehd; k < numnodes; ++k, --i) { X l = node[i].lchild; X r = node[i].rchild; X l = l < NUMVALS ? -(l + 1) : dctreehd - l; X r = r < NUMVALS ? -(r + 1) : dctreehd - r; X put_int(l, ob); X put_int(r, ob); X } X X return sizeof(short) + numnodes * 2 * sizeof(short); X} X X/* X * Get an encoded byte or EOF. Reads from specified stream AS NEEDED. X * X * There are two unsynchronized bit-byte relationships here. The input stream X * bytes are converted to bit strings of various lengths via the static X * variables named c... These bit strings are concatenated without padding to X * become the stream of encoded result bytes, which this function returns one X * at a time. The EOF (end of file) is converted to SPEOF for convenience and X * encoded like any other input value. True EOF is returned after that. X */ X Xstatic int Xgethuff(ib) /* Returns bytes except for EOF */ X FILE *ib; X{ X int rbyte; /* Result byte value */ X int need; /* number of bits */ X int getc_ncr(); X X rbyte = 0; X need = 8; /* build one byte per call */ X X /* X * Loop to build a byte of encoded data. Initialization forces read X * the first time. X */ X Xloop: X if (cbitsrem >= need) { /* if current code is big enough */ X if (need == 0) X return rbyte; X X rbyte |= ccode << (8 - need); /* take what we need */ X ccode >>= need; /* and leave the rest */ X cbitsrem -= need; X return rbyte & 0xff; X } X /* We need more than current code */ X X if (cbitsrem > 0) { X rbyte |= ccode << (8 - need); /* take what there is */ X need -= cbitsrem; X } X /* No more bits in current code string */ X X if (curin == SPEOF) { /* The end of file token has been encoded. If X * result byte has data return it and do EOF X * next time. */ X X cbitsrem = 0; X return (need == 8) ? EOF : rbyte + 0; X } X /* Get an input byte */ X X if ((curin = getc_ncr(ib)) == EOF) X curin = SPEOF; /* convenient for encoding */ X X ccode = code[curin]; /* get the new byte's code */ X cbitsrem = codelen[curin]; X X goto loop; X} X X/* X * This routine is used to perform the actual squeeze operation. It can only X * be called after the file has been scanned. It returns the true length of X * the squeezed entry. X */ X Xlong Xfile_sq(f, t) /* squeeze a file into an archive */ X FILE *f; /* file to squeeze */ X FILE *t; /* archive to receive file */ X{ X int c; /* one byte of squeezed data */ X long size; /* size after squeezing */ X X size = wrt_head(t); /* write out the decode tree */ X X while ((c = gethuff(f)) != EOF) { X putc_pak(c, t); X size++; X } X X return size; /* report true size */ X} SHAR_EOF if test 14548 -ne "`wc -c < 'arcsq.c'`" then echo shar: "error transmitting 'arcsq.c'" '(should have been 14548 characters)' fi fi echo shar: "extracting 'arcsqs.c'" '(11513 characters)' if test -f 'arcsqs.c' then echo shar: "will not over-write existing file 'arcsqs.c'" else sed 's/^X//' << \SHAR_EOF > 'arcsqs.c' X/* X * $Header: arcsqs.c,v 1.3 88/07/31 18:54:14 hyc Exp $ X */ X X/* ARC - Archive utility - SQUASH X X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X X This is a quick hack to ARCLZW to make it handle squashed archives. X Dan Lanciani (ddl@harvard.*) July 87 X X*/ X X/* X * $Header: arcsqs.c,v 1.3 88/07/31 18:54:14 hyc Exp $ X */ X X#include <stdio.h> X#include "arc.h" X X#if MSDOS Xchar *setmem(); X#else Xchar *memset(); X#endif Xint getc_unp(); Xvoid putc_pak(), putc_unp(); Xstatic void putcode(); X X/* definitions for the new dynamic Lempel-Zev crunching */ X X#define BITS 13 /* maximum bits per code */ X#define HSIZE 10007 /* 80% occupancy */ X#define INIT_BITS 9 /* initial number of bits/code */ Xstatic int n_bits; /* number of bits/code */ Xstatic int maxcode; /* maximum code, given n_bits */ X#define MAXCODE(n) ((1<<(n)) - 1) /* maximum code calculation */ Xstatic int maxcodemax = 1 << BITS; /* largest possible code (+1) */ X Xstatic unsigned char buf[BITS]; /* input/output buffer */ X Xstatic unsigned char lmask[9] = /* left side masks */ X{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; Xstatic unsigned char rmask[9] = /* right side masks */ X{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; X Xstatic int offset; /* byte offset for code output */ Xstatic long in_count; /* length of input */ Xstatic long bytes_out; /* length of compressed output */ Xstatic unsigned short ent; X Xlong htab[HSIZE]; /* hash code table (crunch) */ Xunsigned short codetab[HSIZE]; /* string code table (crunch) */ X Xstatic unsigned short *prefix = codetab; /* prefix code table (uncrunch) */ Xstatic unsigned char *suffix=(unsigned char *)htab; /* suffix table (uncrunch) */ Xstatic int free_ent; /* first unused entry */ Xstatic int firstcmp; /* true at start of compression */ Xunsigned char stack[HSIZE]; /* local push/pop stack */ X X/* X * block compression parameters -- after all codes are used up, X * and compression rate changes, start over. X */ X Xstatic int clear_flg; Xstatic long ratio; X#define CHECK_GAP 10000 /* ratio check interval */ Xstatic long checkpoint; X X/* X * the next two codes should not be changed lightly, as they must not X * lie within the contiguous general code space. X */ X#define FIRST 257 /* first free entry */ X#define CLEAR 256 /* table clear output code */ X Xstatic void Xcl_block(t) /* table clear for block compress */ X FILE *t; /* our output file */ X{ X long rat; X X checkpoint = in_count + CHECK_GAP; X X if (in_count > 0x007fffffL) { /* shift will overflow */ X rat = bytes_out >> 8; X if (rat == 0) /* Don't divide by zero */ X rat = 0x7fffffffL; X else X rat = in_count / rat; X } else X rat = (in_count << 8) / bytes_out; /* 8 fractional bits */ X X if (rat > ratio) X ratio = rat; X else { X ratio = 0; X setmem(htab, HSIZE * sizeof(long), 0xff); X free_ent = FIRST; X clear_flg = 1; X putcode(CLEAR, t); X } X} X X/***************************************************************** X * X * Output a given code. X * Inputs: X * code: A n_bits-bit integer. If == -1, then EOF. This assumes X * that n_bits =< (long)wordsize - 1. X * Outputs: X * Outputs code to the file. X * Assumptions: X * Chars are 8 bits long. X * Algorithm: X * Maintain a BITS character long buffer (so that 8 codes will X * fit in it exactly). When the buffer fills up empty it and start over. X */ X Xstatic void Xputcode(code, t) /* output a code */ X int code; /* code to output */ X FILE *t; /* where to put it */ X{ X int r_off = offset; /* right offset */ X int bits = n_bits; /* bits to go */ X unsigned char *bp = buf; /* buffer pointer */ X int n; /* index */ X register int ztmp; X X if (code >= 0) { /* if a real code *//* Get to the first byte. */ X bp += (r_off >> 3); X r_off &= 7; X X /* X * Since code is always >= 8 bits, only need to mask the X * first hunk on the left. X */ X ztmp = (code << r_off) & lmask[r_off]; X *bp = (*bp & rmask[r_off]) | ztmp; X bp++; X bits -= (8 - r_off); X code >>= (8 - r_off); X X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ X if (bits >= 8) { X *bp++ = code; X code >>= 8; X bits -= 8; X } X /* Last bits. */ X if (bits) X *bp = code; X X offset += n_bits; X X if (offset == (n_bits << 3)) { X bp = buf; X bits = n_bits; X bytes_out += bits; X do X putc_pak(*bp++, t); X while (--bits); X offset = 0; X } X /* X * If the next entry is going to be too big for the code X * size, then increase it, if possible. X */ X if (free_ent > maxcode || clear_flg > 0) { /* Write the whole X * buffer, because the X * input side won't X * discover the size X * increase until after X * it has read it. */ X if (offset > 0) { X bp = buf; /* reset pointer for writing */ X bytes_out += n = n_bits; X while (n--) X putc_pak(*bp++, t); X } X offset = 0; X X if (clear_flg) { /* reset if clearing */ X maxcode = MAXCODE(n_bits = INIT_BITS); X clear_flg = 0; X } else {/* else use more bits */ X n_bits++; X if (n_bits == BITS) X maxcode = maxcodemax; X else X maxcode = MAXCODE(n_bits); X } X } X } else { /* dump the buffer on EOF */ X bytes_out += n = (offset + 7) / 8; X X if (offset > 0) X while (n--) X putc_pak(*bp++, t); X offset = 0; X } X} X X/***************************************************************** X * X * Read one code from the standard input. If EOF, return -1. X * Inputs: X * cmpin X * Outputs: X * code or -1 is returned. X */ X Xstatic int Xgetcode(f) /* get a code */ X FILE *f; /* file to get from */ X{ X int code; X static int loffset = 0, size = 0; X int r_off, bits; X unsigned char *bp = buf; X X if (clear_flg > 0 || loffset >= size || free_ent > maxcode) { X /* If the next entry will be too big for the current code X * size, then we must increase the size. This implies reading X * a new buffer full, too. */ X if (free_ent > maxcode) { X n_bits++; X if (n_bits == BITS) X maxcode = maxcodemax; /* won't get any bigger X * now */ X else X maxcode = MAXCODE(n_bits); X } X if (clear_flg > 0) { X maxcode = MAXCODE(n_bits = INIT_BITS); X clear_flg = 0; X } X for (size = 0; size < n_bits; size++) { X if ((code = getc_unp(f)) == EOF) X break; X else X buf[size] = code; X } X if (size <= 0) X return -1; /* end of file */ X X loffset = 0; X /* Round size down to integral number of codes */ X size = (size << 3) - (n_bits - 1); X } X r_off = loffset; X bits = n_bits; X X /* X * Get to the first byte. X */ X bp += (r_off >> 3); X r_off &= 7; X X /* Get first part (low order bits) */ X code = (*bp++ >> r_off); X bits -= 8 - r_off; X r_off = 8 - r_off; /* now, offset into code word */ X X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ X if (bits >= 8) { X code |= *bp++ << r_off; X r_off += 8; X bits -= 8; X } X /* high order bits. */ X code |= (*bp & rmask[bits]) << r_off; X loffset += n_bits; X X return code; X} X X/* X * compress a file X * X * Algorithm: use open addressing double hashing (no chaining) on the X * prefix code / next character combination. We do a variant of Knuth's X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime X * secondary probe. Here, the modular division first probe is gives way X * to a faster exclusive-or manipulation. Also do block compression with X * an adaptive reset, where the code table is cleared when the compression X * ratio decreases, but after the table fills. The variable-length output X * codes are re-sized at this point, and a special CLEAR code is generated X * for the decompressor. X */ X Xvoid Xsqinit_cm() /* initialize for compression */ X{ X offset = 0; X bytes_out = 0; X clear_flg = 0; X ratio = 0; X in_count = 1; X checkpoint = CHECK_GAP; X maxcode = MAXCODE(n_bits = INIT_BITS); X free_ent = FIRST; X setmem(htab, HSIZE * sizeof(long), 0xff); X n_bits = INIT_BITS; /* set starting code size */ X X firstcmp = 1; /* next byte will be first */ X} X Xvoid Xsqputc_cm(c, t) /* compress a character */ X unsigned char c; /* character to compress */ X FILE *t; /* where to put it */ X{ X static long fcode; X static int hshift; X int i; X int disp; X X if (firstcmp) { /* special case for first byte */ X ent = c; /* remember first byte */ X X hshift = 0; X for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L) X hshift++; X hshift = 8 - hshift; /* set hash code range bund */ X X firstcmp = 0; /* no longer first */ X return; X } X in_count++; X fcode = (long) (((long) c << BITS) + ent); X i = (c << hshift) ^ ent;/* xor hashing */ X X if (htab[i] == fcode) { X ent = codetab[i]; X return; X } else if (htab[i] < 0) /* empty slot */ X goto nomatch; X disp = HSIZE - i; /* secondary hash (after G.Knott) */ X if (i == 0) X disp = 1; X Xprobe: X if ((i -= disp) < 0) X i += HSIZE; X X if (htab[i] == fcode) { X ent = codetab[i]; X return; X } X if (htab[i] > 0) X goto probe; X Xnomatch: X putcode(ent, t); X ent = c; X if (free_ent < maxcodemax) { X codetab[i] = free_ent++; /* code -> hashtable */ X htab[i] = fcode; X } else if ((long) in_count >= checkpoint) X cl_block(t); X} X Xlong Xsqpred_cm(t) /* finish compressing a file */ X FILE *t; /* where to put it */ X{ X putcode(ent, t); /* put out the final code */ X putcode(-1, t); /* tell output we are done */ X X return bytes_out; /* say how big it got */ X} X X/* X * Decompress a file. This routine adapts to the codes in the file X * building the string table on-the-fly; requiring no table to be stored X * in the compressed file. The tables used herein are shared with those of X * the compress() routine. See the definitions above. X */ X Xvoid Xsqdecomp(f, t) /* decompress a file */ X FILE *f; /* file to read codes from */ X FILE *t; /* file to write text to */ X{ X unsigned char *stackp; X int finchar; X int code, oldcode, incode; X X n_bits = INIT_BITS; /* set starting code size */ X clear_flg = 0; X X /* X * As above, initialize the first 256 entries in the table. X */ X maxcode = MAXCODE(n_bits = INIT_BITS); X for (code = 255; code >= 0; code--) { X prefix[code] = 0; X suffix[code] = (unsigned char) code; X } X free_ent = FIRST; X X finchar = oldcode = getcode(f); X if (oldcode == -1) /* EOF already? */ X return; /* Get out of here */ X putc_unp((char) finchar, t); /* first code must be 8 bits=char */ X stackp = stack; X X while ((code = getcode(f)) > -1) { X if (code == CLEAR) { X for (code = 255; code >= 0; code--) X prefix[code] = 0; X clear_flg = 1; X free_ent = FIRST - 1; X if ((code = getcode(f)) == -1) /* O, untimely death! */ X break; X } X incode = code; X /* X * Special case for KwKwK string. X */ X if (code >= free_ent) { X if (code > free_ent) { X if (warn) { X printf("Corrupted compressed file.\n"); X printf("Invalid code %d when max is %d.\n", X code, free_ent); X } X nerrs++; X return; X } X *stackp++ = finchar; X code = oldcode; X } X /* X * Generate output characters in reverse order X */ X while (code >= 256) { X *stackp++ = suffix[code]; X code = prefix[code]; X } X *stackp++ = finchar = suffix[code]; X X /* X * And put them out in forward order X */ X do X putc_unp(*--stackp, t); X while (stackp > stack); X X /* X * Generate the new entry. X */ X if ((code = free_ent) < maxcodemax) { X prefix[code] = (unsigned short) oldcode; X suffix[code] = finchar; X free_ent = code + 1; X } X /* X * Remember previous code. X */ X oldcode = incode; X } X} SHAR_EOF if test 11513 -ne "`wc -c < 'arcsqs.c'`" then echo shar: "error transmitting 'arcsqs.c'" '(should have been 11513 characters)' fi fi echo shar: "extracting 'arcsvc.c'" '(4689 characters)' if test -f 'arcsvc.c' then echo shar: "will not over-write existing file 'arcsvc.c'" else sed 's/^X//' << \SHAR_EOF > 'arcsvc.c' X/* X * $Header: arcsvc.c,v 1.9 88/07/31 18:54:55 hyc Exp $ X */ X X/* ARC - Archive utility - ARCSVC X X Version 2.23, created on 04/22/87 at 13:10:10 X X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED X X By: Thom Henderson X X Description: X This file contains service routines needed to maintain an archive. X X Language: X Computer Innovations Optimizing C86 X*/ X#include <stdio.h> X#include "arc.h" X#if MTS X#include <mts.h> X#endif X Xvoid abort(), setstamp(); Xint unlink(); X Xvoid Xopenarc(chg) /* open archive */ X int chg; /* true to open for changes */ X{ X FILE *fopen();/* file opener */ X X if (!(arc = fopen(arcname, OPEN_R))) { X if (chg) { X if (note) X printf("Creating new archive: %s\n", arcname); X } X else X abort("Archive not found: %s", arcname); X } X#if MTS X /* allow reading archives of max MTS record length */ X else { X char *buffer, *malloc(); X int inlen; X struct GDDSECT *region; X X region=gdinfo(arc->_fd._fdub); X inlen=region->GDINLEN; X buffer=malloc(inlen); X setbuf(arc, buffer); X arc->_bufsiz=inlen; X } X#endif X if (chg) { /* if opening for changes */ X if (!(new = fopen(newname, OPEN_W))) X abort("Cannot create archive copy: %s", newname); X X changing = chg; /* note if open for changes */ X } X} X Xvoid Xclosearc(chg) /* close an archive */ X int chg; /* true if archive was changed */ X{ X if (arc) { /* if we had an initial archive */ X fclose(arc); X#if !MTS X if (kludge) /* kludge to update timestamp */ X setstamp(arcname, olddate, oldtime); X#endif X } X if (chg) { /* if things have changed */ X fclose(new); /* close the new copy */ X if (arc) { /* if we had an original archive */ X if (keepbak) { /* if a backup is wanted */ X unlink(bakname); /* erase any old copies */ X if (move(arcname, bakname)) X abort("Cannot rename %s to %s", arcname, bakname); X printf("Keeping backup archive: %s\n", bakname); X } else if (unlink(arcname)) X abort("Cannot delete old archive: %s", arcname); X } X if (move(newname, arcname)) X abort("Cannot move %s to %s", newname, arcname); X#if !MTS X setstamp(arcname, arcdate, arctime); X#endif X } X} X X/* X * CRC computation logic X * X * The logic for this method of calculating the CRC 16 bit polynomial is taken X * from an article by David Schwaderer in the April 1985 issue of PC Tech X * Journal. X */ X Xstatic short crctab[] = /* CRC lookup table */ X{ X 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 X}; X Xint Xaddcrc(crc, c) /* update a CRC check */ X int crc; /* running CRC value */ X unsigned char c; /* character to add */ X{ X return ((crc >> 8) & 0x00ff) ^ crctab[(crc ^ c) & 0x00ff]; X} SHAR_EOF if test 4689 -ne "`wc -c < 'arcsvc.c'`" then echo shar: "error transmitting 'arcsvc.c'" '(should have been 4689 characters)' fi fi echo shar: "extracting 'arctst.c'" '(1284 characters)' if test -f 'arctst.c' then echo shar: "will not over-write existing file 'arctst.c'" else sed 's/^X//' << \SHAR_EOF > 'arctst.c' X/* X * $Header: arctst.c,v 1.4 88/04/19 01:40:28 hyc Exp $ X */ X X/* X * ARC - Archive utility - ARCTST X * X * Version 2.12, created on 02/03/86 at 23:00:40 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to test archive integrity. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X Xvoid openarc(); Xint readhdr(), unpack(); X Xvoid Xtstarc() X{ /* test integrity of an archive */ X struct heads hdr; /* file header */ X long arcsize, ftell(); /* archive size */ X X openarc(0); /* open archive for reading */ X fseek(arc, 0L, 2); /* move to end of archive */ X arcsize = ftell(arc); /* see how big it is */ X fseek(arc, 0L, 0); /* return to top of archive */ X X while (readhdr(&hdr, arc)) { X if (ftell(arc) + hdr.size > arcsize) { X printf("Archive truncated in file %s\n", hdr.name); X nerrs++; X break; X } else { X printf("Testing file: %-12s ", hdr.name); X fflush(stdout); X if (unpack(arc, NULL, &hdr)) X nerrs++; X else X printf("okay\n"); X } X } X X if (nerrs < 1) X printf("No errors detected\n"); X else if (nerrs == 1) X printf("One error detected\n"); X else X printf("%d errors detected\n", nerrs); X} SHAR_EOF if test 1284 -ne "`wc -c < 'arctst.c'`" then echo shar: "error transmitting 'arctst.c'" '(should have been 1284 characters)' fi fi echo shar: "extracting 'arcunp.c'" '(5347 characters)' if test -f 'arcunp.c' then echo shar: "will not over-write existing file 'arcunp.c'" else sed 's/^X//' << \SHAR_EOF > 'arcunp.c' X/* X * $Header: arcunp.c,v 1.7 88/06/18 03:12:36 hyc Locked $ X */ X X/* X * ARC - Archive utility - ARCUNP X * X * Version 3.17, created on 02/13/86 at 10:20:08 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to expand a file when X * taking it out of an archive. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X#if MTS X#include <ctype.h> X#endif X Xvoid setcode(), init_usq(), init_ucr(), decomp(), sqdecomp(); Xvoid abort(), putc_tst(); Xint getc_usq(), getc_ucr(), addcrc(); X X/* stuff for repeat unpacking */ X X#define DLE 0x90 /* repeat byte flag */ X Xstatic int state; /* repeat unpacking state */ X X/* repeat unpacking states */ X X#define NOHIST 0 /* no relevant history */ X#define INREP 1 /* sending a repeated value */ X Xstatic short crcval; /* CRC check value */ Xstatic long size; /* bytes to read */ X#if !DOS Xstatic int gotcr; /* got a carriage return? */ X#endif X Xint Xunpack(f, t, hdr) /* unpack an archive entry */ X FILE *f, *t; /* source, destination */ X struct heads *hdr; /* pointer to file header data */ X{ X int c; /* one char of stream */ X void putc_unp(); X void putc_ncr(); X int getc_unp(); X X /* setups common to all methods */ X#if !DOS X gotcr = 0; X#endif X crcval = 0; /* reset CRC check value */ X size = hdr->size; /* set input byte counter */ X state = NOHIST; /* initial repeat unpacking state */ X setcode(); /* set up for decoding */ X X /* use whatever method is appropriate */ X X switch (hdrver) { /* choose proper unpack method */ X case 1: /* standard packing */ X case 2: X while ((c = getc_unp(f)) != EOF) X putc_unp((char) c, t); X break; X X case 3: /* non-repeat packing */ X while ((c = getc_unp(f)) != EOF) X putc_ncr((unsigned char) c, t); X break; X X case 4: /* Huffman squeezing */ X init_usq(f); X while ((c = getc_usq(f)) != EOF) X putc_ncr((unsigned char) c, t); X break; X X case 5: /* Lempel-Zev compression */ X init_ucr(0); X while ((c = getc_ucr(f)) != EOF) X putc_unp((char) c, t); X break; X X case 6: /* Lempel-Zev plus non-repeat */ X init_ucr(0); X while ((c = getc_ucr(f)) != EOF) X putc_ncr((unsigned char) c, t); X break; X X case 7: /* L-Z plus ncr with new hash */ X init_ucr(1); X while ((c = getc_ucr(f)) != EOF) X putc_ncr((unsigned char) c, t); X break; X X case 8: /* dynamic Lempel-Zev */ X decomp(f, t); X break; X X case 9: /* Squashing */ X sqdecomp(f, t); X break; X X default: /* unknown method */ X if (warn) { X printf("I don't know how to unpack file %s\n", hdr->name); X printf("I think you need a newer version of ARC\n"); X nerrs++; X } X fseek(f, hdr->size, 1); /* skip over bad file */ X return 1; /* note defective file */ X } X X /* cleanups common to all methods */ X X if (crcval != hdr->crc) { X if (warn || kludge) { X printf("WARNING: File %s fails CRC check\n", hdr->name); X nerrs++; X } X return 1; /* note defective file */ X } X return 0; /* file is okay */ X} X X/* X * This routine is used to put bytes in the output file. It also performs X * various housekeeping functions, such as maintaining the CRC check value. X */ X Xvoid Xputc_unp(c, t) /* output an unpacked byte */ X char c; /* byte to output */ X FILE *t; /* file to output to */ X{ X crcval = addcrc(crcval, c); /* update the CRC check value */ X#if MTS X if (!image) X atoe(&c, 1); X#endif X#if DOS X putc_tst(c, t); X#else X if (image) X putc_tst(c, t); X else { X if (gotcr) { X gotcr = 0; X if (c != '\n') X putc_tst('\r', t); X } X if (c == '\r') X gotcr = 1; X else X putc_tst(c, t); X } X#endif X} X X/* X * This routine is used to decode non-repeat compression. Bytes are passed X * one at a time in coded format, and are written out uncoded. The data is X * stored normally, except that runs of more than two characters are X * represented as: X * X * <char> <DLE> <count> X * X * With a special case that a count of zero indicates a DLE as data, not as a X * repeat marker. X */ X Xvoid Xputc_ncr(c, t) /* put NCR coded bytes */ X unsigned char c; /* next byte of stream */ X FILE *t; /* file to receive data */ X{ X static int lastc; /* last character seen */ X X switch (state) { /* action depends on our state */ X case NOHIST: /* no previous history */ X if (c == DLE) /* if starting a series */ X state = INREP; /* then remember it next time */ X else X putc_unp(lastc = c, t); /* else nothing unusual */ X return; X X case INREP: /* in a repeat */ X if (c) /* if count is nonzero */ X while (--c) /* then repeatedly ... */ X putc_unp(lastc, t); /* ... output the byte */ X else X putc_unp(DLE, t); /* else output DLE as data */ X state = NOHIST; /* back to no history */ X return; X X default: X abort("Bad NCR unpacking state (%d)", state); X } X} X X/* X * This routine provides low-level byte input from an archive. This routine X * MUST be used, as end-of-file is simulated at the end of the archive entry. X */ X Xint Xgetc_unp(f) /* get a byte from an archive */ X FILE *f; /* archive file to read */ X{ X register int xx; X unsigned char code(); X X if (!size) /* if no data left */ X return EOF; /* then pretend end of file */ X X size--; /* deduct from input counter */ X xx = getc(f); X return code(xx); /* and return next decoded byte */ X} SHAR_EOF if test 5347 -ne "`wc -c < 'arcunp.c'`" then echo shar: "error transmitting 'arcunp.c'" '(should have been 5347 characters)' fi fi echo shar: "extracting 'arcusq.c'" '(2486 characters)' if test -f 'arcusq.c' then echo shar: "will not over-write existing file 'arcusq.c'" else sed 's/^X//' << \SHAR_EOF > 'arcusq.c' X/* X * $Header: arcusq.c,v 1.2 88/06/02 16:27:44 hyc Locked $ X */ X X/* X * ARC - Archive utility - ARCUSQ X * X * Version 3.14, created on 07/25/86 at 13:04:19 X * X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED X * X * By: Thom Henderson X * X * Description: This file contains the routines used to expand a file which was X * packed using Huffman squeezing. X * X * Most of this code is taken from an USQ program by Richard Greenlaw, which was X * adapted to CI-C86 by Robert J. Beilstein. X * X * Language: Computer Innovations Optimizing C86 X */ X#include <stdio.h> X#include "arc.h" X Xvoid abort(); Xint getc_unp(); X X/* stuff for Huffman unsqueezing */ X X#define ERROR (-1) X X#define SPEOF 256 /* special endfile token */ X#define NUMVALS 257 /* 256 data values plus SPEOF */ X Xextern struct nd { /* decoding tree */ X int child[2]; /* left, right */ X} node[NUMVALS]; /* use large buffer */ X Xstatic int bpos; /* last bit position read */ Xstatic int curin; /* last byte value read */ Xstatic int numnodes; /* number of nodes in decode tree */ X Xstatic short Xget_int(f) /* get a 16bit integer */ X FILE *f; /* file to get it from */ X{ X int i,j; X i = getc_unp(f); X j = getc_unp(f) << 8; X return (i | j) & 0xFFFF; X} X Xvoid Xinit_usq(f) /* initialize Huffman unsqueezing */ X FILE *f; /* file containing squeezed data */ X{ X int i; /* node index */ X X bpos = 99; /* force initial read */ X X numnodes = get_int(f); X X if (numnodes < 0 || numnodes >= NUMVALS) X abort("File has an invalid decode tree"); X X /* initialize for possible empty tree (SPEOF only) */ X X node[0].child[0] = -(SPEOF + 1); X node[0].child[1] = -(SPEOF + 1); X X for (i = 0; i < numnodes; ++i) { /* get decoding tree from X * file */ X node[i].child[0] = get_int(f); X node[i].child[1] = get_int(f); X } X} X Xint Xgetc_usq(f) /* get byte from squeezed file */ X FILE *f; /* file containing squeezed data */ X{ X short i; /* tree index */ X X /* follow bit stream in tree to a leaf */ X X for (i = 0; i >= 0;) { /* work down(up?) from root */ X if (++bpos > 7) { X if ((curin = getc_unp(f)) == ERROR) X return (ERROR); X bpos = 0; X X /* move a level deeper in tree */ X i = node[i].child[1 & curin]; X } else X i = node[i].child[1 & (curin >>= 1)]; X } X X /* decode fake node index to original data value */ X X i = -(i + 1); X X /* decode special endfile token to normal EOF */ X X i = (i == SPEOF) ? EOF : i; X return i; X} SHAR_EOF if test 2486 -ne "`wc -c < 'arcusq.c'`" then echo shar: "error transmitting 'arcusq.c'" '(should have been 2486 characters)' fi fi echo shar: "extracting 'getwd.c'" '(786 characters)' if test -f 'getwd.c' then echo shar: "will not over-write existing file 'getwd.c'" else sed 's/^X//' << \SHAR_EOF > 'getwd.c' X/* X * 4.2bsd getwd simulation for Sys V.3 X */ X X#include <stdio.h> X X#undef SYSV3 X X#define MAXWD 1024 /* limited by 4.2 getwd(2) */ X X#ifdef SYSV3 X Xchar *getcwd(); X Xchar * Xgetwd(path) Xchar *path; X{ X return(getcwd(path,MAXWD)); X} X X#else X X/* X * 4.2bsd getwd simulation for Sys V.2 X */ X X#include <stdio.h> X X#define MAXWD 1024 /* limited by 4.2 getwd(2) */ X Xchar * Xgetwd(path) Xchar *path; X{ X char *nlp; X FILE *fp; X FILE *popen(); X char *strrchr(); X X putenv("IFS= \t\n"); X fp = popen("PATH=/bin:/usr/bin pwd", "r"); X if (fp == NULL) X return 0; X if (fgets(path, MAXWD, fp) == NULL) { X (void) pclose(fp); X return 0; X } X if ((nlp = strrchr(path, '\n')) != NULL) X *nlp = '\0'; X (void) pclose(fp); X return path; X} X#endif X SHAR_EOF if test 786 -ne "`wc -c < 'getwd.c'`" then echo shar: "error transmitting 'getwd.c'" '(should have been 786 characters)' fi fi exit 0 # End of shell archive