Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!uunet!munnari!murdu!u3369429 From: u3369429@murdu.OZ (Michael Bednarek) Newsgroups: comp.os.vms Subject: shar (sort of) for VMS Version 3.06 Message-ID: <1270@murdu.OZ> Date: Tue, 30-Jun-87 03:34:07 EDT Article-I.D.: murdu.1270 Posted: Tue Jun 30 03:34:07 1987 Date-Received: Sat, 4-Jul-87 22:37:14 EDT Followup-To: comp.os.vms Distribution: world Organization: I.A.E.S.R., Melbourne University Lines: 360 Keywords: shar source programs Summary: A new (3.06) release of VMS_SHAR Hi netlanders! Three weeks ago, I published my VMS_SHAR procedure. This prompted a lot of useful reactions from you. So I went back to the drawing board and re-wrote it. Not all suggestions have been implemented, yet. Blurb and history are included in the procedure itself. Michael Bednarek u3369429@{murdu.oz.au | xvax.dn.mu.oz.au} "POST NO BILLS." ....................... Cut between dotted lines and save ...................... $!.............................................................................. $! VAX/VMS archive file created by VMS_SHAR V-3.06 30-Jun-1987 $! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au) $! To unpack, simply save and execute (@) this file. $! $! This archive was created by U3369429 (Michael Bednarek) $! on Tuesday 30-JUN-1987 17:19:59.44 $! $! It contains the following 1 file: $! VMS_SHAR.COM $!============================================================================== $ Set Symbol/Scope=(NoLocal,NoGlobal) $!See what VMS version we have here: $ Version=F$GetSYI("VERSION") $ If Version.ges."V4.4" then goto Version_OK $ Write SYS$Output "Sorry, you are running VMS ",Version, - ", but this procedure requires V4.4 or higher." $ Exit 44 $Version_OK: CR[0,8]=13 $ Pass_or_Failed="failed!,passed." $ Goto Start $Convert_File: $ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd $No_Error1: Define/User_Mode SYS$Output NL: $ EDIT/EDT/NoJournal/Output='File_is' VMS_SHAR_DUMMY.DUMMY Set Quiet; Change; 32000(D+C L) Exit $ Delete VMS_SHAR_DUMMY.DUMMY;* $ Checksum 'File_is $ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR $ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd $No_Error2: Return $Start: $ File_is="VMS_SHAR.COM" $ Check_Sum_is=992556736 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY X$ Verify='F$Verify(0) X$ Facility_Name= "VMS_SHAR" X$ Facility_Version= "V-3.06 30-Jun-1987" X$! X$ SS$_Abort=44 X$ On Control_Y then goto Abort X$ On Error then Continue X$! X$!Michael Bednarek u3369429@{murdu.oz.au | ucsvc.dn.mu.oz.au} X$!Institute of Applied Economic -- or -- X$! and Social Research (IAESR) ...seismo.CSS.GOV!munnari! X$!Melbourne University {murdu.oz | ucsvc.dn.mu.oz}!u3369429 X$!Parkville 3052, Phone : +61 3 344 5744 X$!AUSTRALIA X$! X$! Copyright (c) 1987, by Michael Bednarek X$! The distribution of this file is unrestricted as long as this notice X$! remains intact. X$! X$! Usage: @VMS_SHAR file[,file...] sharfile X$! where file are file names, separated by commas, possibly including X$! wild-card characters, of those files that are to be packaged. X$! sharfile is the resulting self-unpacking archive file. X$! VAX/VMS version 4.4 or higher X$! X$ Goto Start X$Abort: X$ Close/Error=Anyway Out X$Anyway: X$ Exit SS$_Abort X XREAD_ME: X XFeatures: X o Through the use of SET SYMBOL/SCOPE=(NOLOCAL,NOGLOBAL) both VMS_SHAR X and the procedures created by it are very rubust against local X idiosyncrasies with symbols. Imagine a user who does: IF=="!" ! X o The resulting file gives the username of its creator and date/time X of creation. If the global symbol REAL_NAME exists, its content is X also displayed. X o The resulting file contains a list of all its files. X o At creation time, each line is preceded by character 'X' which is X removed at unpacking time. This is to preserve leading tabs/spaces X through various mailers. X o Some mailers disallow postings above a certain size. VMS_SHAR will check X that the resulting file will not exceed MAX_PART_SIZE which is currently X set to 31 blocks (our mailer disallows postings >16000 characters). X If more than 31 blocks are to be posted, VMS_SHAR will create multiple X files by appending a 'part number' to the output file name. X If one single input file exceeds MAX_PART_SIZE the user will be notified, X and 'part number' will be incremented such that subsequent manual splitting X has free 'part numbers' available. X o At both creation and unpacking time, each file is CHECKSUMmed; the result X of the comparison of both values is displayed to the user. X o Signatures and such, which might occur at the end of each part, don't X need to be stripped. They are skipped by the unpacking procedure. X o The created procedure will check for VMS version 4.4 or higher. X XAbout Version 2.00: X Mainly a cleaning-up re-write. Fixed the case where full pathnames were X given. Also checks now whether the output filename is among the input X filenames. X The procedure now performs in two distinct steps: X a) collecting file names and their size information, X b) actually packaging the files. X This allows to include an indication of the number of parts at the top X of the resulting file. It also allows to omit part-suffixes if not required. X However, under rare circumstances this might not work. X One condition which springs to mind where it doesn't work is: X You package two files, the first one 30 blocks, the second 1 block. X Let's call the difference between 512 and the number of bytes which are X actually used in the first file's last block "spare bytes". X If the number of lines in the first file is greater than 512+"spare bytes", X then VMS_SHAR will attempt to create a filename for part 2, but it has not X been properly initialised and will fail. Well, not really. It will complain X about an unknown symbol "I", and will not append its version suffixes, but X will still create the files, only using standard VMS version increments. X X Another case which is insufficiently handled is when one single file X exceeds MAX_PART_SIZE. The whole numbering scheme gets out of kilter X and the packager is left with a renaming task. X XAbout Version 3.00: X I had some discussions with usenet members, particularly with X Ed about trailing white space. X He suggested to use a length count at the beginning of each line, and to X split lines longer than 80 characters and restore them at the receiving X site. X I didn't follow that suggestion for three reasons: X 1. The unix shar doesn't cater for this either. X 2. It would have increased processing time a lot. X 3. I didn't ever experience serious difficulties due to lost trailing X white space. X X However, it was Ed who came up with a method to use EDT to insert/remove X those leading "X"s. As this turned out to be 3 times faster than my X previous method (OPEN/READ/lexical function/WRITE) this was implemented X in version 3.00 X X Some days later, after some more good arguments and examples from Ed: X OK, I'm convinced that splitting lines is a good idea. X However, this will take some time to implement as it needs to be done X in TPU and I'm a complete TPU agnostic. But that's what producing these X toys is all about, no? Playful learning. X X The created procedure will now have "Goto " at the end of X each part and "Exit" as its last statement. This should take care of X signatures which might occur at the end of each part. X X$Start: X$ User=F$Edit(F$GetJPI("","USERNAME"),"COLLAPSE") X$ If F$Type(Real_Name).nes."" then User=User+" ("+Real_Name+")" X$ Set="Set" X$ Set Symbol/Scope=(NoLocal,NoGlobal) X$ If P1.eqs."" then Inquire P1 "_File(s) to package" X$ If P1.eqs."" then Exit SS$_Abort X$ If P2.eqs."" then Inquire P2 "_Output Archive" X$ If P2.eqs."" then Exit SS$_Abort X$ File_List=P1 X$ Shar_File=F$Parse(P2)-";" X$! X$ MAX_PART_SIZE=31 ! 31 blocks will keep us below 16000 bytes X$! As this procedure adds a 'X' in the first position of every line, the X$! resulting file can still become larger than MAX_PART_SIZE X$! X$ BEL[0,7]=7 X$ Say="Write SYS$Output" X$ Say Facility_Name," ",Facility_Version X$ Say "" X$! X$! Collect all filenames X$ nParts=1 X$ Part_Size=0 X$ nE=-1 X$ nF=1 X$Next_Element: X$ nF=nF-1 X$ nE=nE+1 X$ Element=F$Element(nE,",",File_List) X$ If Element.eqs."," then goto Elements_Done X$ Previous_File="no file" X$! X$Next_File: X$ nF=nF+1 X$ File'nF=F$Search(Element) X$ If File'nF.eqs.Previous_File then goto Next_Element X$ If File'nF.nes."" then goto Look X$ If Previous_File.eqs."no file" then - X Say "%VMS_SHAR-I-FNF, file not found: ",Element X$ Goto Next_Element X$Look: X$ Previous_File=File'nF X$ Say "looking at ",File'nF X$ If F$Element(0,";",File'nF).nes.Shar_File then goto Not_Silly X$ Say "You can't have your outputfile among the input files!" X$ Exit SS$_Abort X$Not_Silly: X$ Size'nF=F$File_Attributes(File'nF,"EOF") X$ Part_Size=Part_Size+Size'nF X$ If Part_Size.le.MAX_PART_SIZE then goto Next_File X$ nParts=nParts+1 X$ Part_Size=0 X$ Goto Next_File X$! X$Elements_Done: X$ If nF.gt.0 then goto Intro X$ Say "%VMS_SHAR-W-SEARCHFAIL, error searching for",P1 X$ Say "-VMS_SHAR-E-FNF, file not found. No file to package. Nothing done." X$ Exit SS$_Abort X$! X$Intro: X$ Time=F$CVTime(,,"Weekday")+" "+F$CVTime(,"Absolute","DateTime") X$! X$ Part_Name="" X$ Of_Name="" X$ If nParts.lt.2 then goto Only_One1 X$ Of_Name=F$FAO("_OF_!ZL",nParts) X$ i=1 ! i=LOG10(nParts)+1 X$ If nParts.gt.9 then i=2 X$ If nParts.gt.99 then i=3 ! We don't expect more than 999 files X$ Part_Name=F$FAO("!#ZL",i,1) X$Only_One1: X$ Copy NL: 'Shar_File''Part_Name''Of_Name X$ Open/Append Out 'Shar_File''Part_Name''Of_Name X$ Write Out F$FAO("!23*. Cut between dotted lines and save !22*.") X$ Write Out F$FAO("$!!!78*.") X$ Write Out "$! VAX/VMS archive file created by ",Facility_Name," ", - X Facility_Version X$ Write Out "$! which was written by Michael Bednarek ",- X "(U3369429@ucsvc.dn.mu.oz.au)" X$ Write Out "$! To unpack, simply save and execute (@) this file. X$ Write Out "$!" X$ Write Out "$! This archive was created by ''User'" X$ Write Out "$! on ''Time'" X$ Write Out "$!" X$ If nParts.lt.2 then goto Only_One2 X$ Write Out "$! ATTENTION: To keep each article below ", - X F$Integer(MAX_PART_SIZE*512)," bytes, this program" X$ Write Out "$! has been transmitted in ",nParts," parts." X$ Write Out "$! You should concatenate ALL parts to ONE file and execute ", - X "(@) that file." X$ Write Out "$!" X$! X$Only_One2: X$ Write Out F$FAO("$!! It contains the following !UL file!%S:",nF) X$! X$ Files="" X$ n=0 X$Next_Name: X$ n=n+1 X$ Name=F$Parse(File'n,,,"NAME")+F$Parse(File'n,,,"TYPE") X$ If F$Length(Files)+F$Length(Name).le.77 then goto Same_Line X$ Write Out "$!",Files X$ Files="" X$Same_Line: X$ Files=Files+" "+Name X$ If n.lt.nF then Goto Next_Name X$! X$ Write Out "$!",Files X$ Close Out X$ Append SYS$Input 'Shar_File''Part_Name''Of_Name X$ Deck/Dollars="SUBROUTINE_EOF" X$!============================================================================== X$ Set Symbol/Scope=(NoLocal,NoGlobal) X$!See what VMS version we have here: X$ Version=F$GetSYI("VERSION") X$ If Version.ges."V4.4" then goto Version_OK X$ Write SYS$Output "Sorry, you are running VMS ",Version, - X ", but this procedure requires V4.4 or higher." X$ Exit 44 X$Version_OK: CR[0,8]=13 X$ Pass_or_Failed="failed!,passed." X$ Goto Start X$Convert_File: X$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd X$No_Error1: Define/User_Mode SYS$Output NL: X$ EDIT/EDT/NoJournal/Output='File_is' VMS_SHAR_DUMMY.DUMMY XSet Quiet; Change; 32000(D+C L) XExit X$ Delete VMS_SHAR_DUMMY.DUMMY;* X$ Checksum 'File_is X$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR X$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd X$No_Error2: Return X$Start: XSUBROUTINE_EOF X$! X$ n=0 X$Extract_Next: X$ n=n+1 X$ Name=F$Parse(File'n,,,"NAME")+F$Parse(File'n,,,"TYPE") X$ Part_Size=F$File_Attributes("''Shar_File'''Part_Name'''Of_Name'","EOF")+Size'n X$ If Part_Size.le.MAX_PART_SIZE then goto Same_Part1 X$ Open/Append Out 'Shar_File''Part_Name''Of_Name X$! Warning: this will not work if in the course of packaging the files it X$! turns out that by adding all those "X"s an archive suddenly needs more than X$! one part. The probability for this is rather low, though, because the X$! combined files are on average 256*(Number of files) bytes shorter than X$! their individual block numbers added. X$ Part_Name=F$FAO("!#ZL",i,F$Integer(Part_Name)+1) X$ If Size'n.le.MAX_PART_SIZE then goto Fits X$ Say "" X$ Say "The file ",File'n X$ Say "is ",F$Integer(Size'n-MAX_PART_SIZE),- X " blocks larger than MAX_PART_SIZE.",BEL X$ Say "You will have to carve up that file manually." X$ Say "I'll attempt to increment the part number appropriately" X$ Current_Part=F$Integer(Part_Name) X$ Part_Name=F$FAO("!#ZL",i,F$Integer(Size'n/MAX_PART_SIZE)+Current_Part) X$ Current_Part=F$FAO("!#ZL",i,Current_Part) X$ Say "The file ",Shar_File,Part_Name,Of_Name," should be split into",BEL X$ Say Shar_File,Current_Part,Of_Name," to ",Shar_File,Part_Name,Of_Name X$ Say "NOTE: the common suffix ",Of_Name," is now also wrong." X$ Say "I'm afraid you have to rename all files manually." X$ Read/End_of_File=Fits/Prompt="Enter to continue " SYS$Command ddd X$Fits: X$ Write Out "$ Goto Part''Part_name'" X$ Close Out X$ Say "" X$ Say "Now writing to ",Shar_File,Part_Name,Of_Name X$ Copy NL: 'Shar_File''Part_Name''Of_Name X$ Open/Append Out 'Shar_File''Part_Name''Of_Name X$ Write Out "$Part''Part_Name':" X$Same_Part1: X$ Say "appending ",File'n X$ If F$TRNLNM("Out").eqs."" then Open/Append Out 'Shar_File''Part_Name''Of_Name X$ Write Out "$ File_is=""''Name'""" X$ Checksum &File'n X$ Write Out "$ Check_Sum_is=''CHECKSUM$CHECKSUM'" X$ Write Out "$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY" X$ Close Out X$ Define/User_Mode SYS$Output NL: X$ EDIT/EDT/NoJournal/Output=VMS_SHAR_DUMMY.DUMMY &File'n XSet Quiet; Change; ER -L 32000(88ASC -2L) XExit X$ Append VMS_SHAR_DUMMY.DUMMY 'Shar_File''Part_Name''Of_Name X$ Delete VMS_SHAR_DUMMY.DUMMY;* X$ Append SYS$Input 'Shar_File''Part_Name''Of_Name X$ Deck/Dollars="Just_1" X$ GoSub Convert_File XJust_1 X$ If n.lt.nF then goto Extract_Next X$ Append SYS$Input 'Shar_File''Part_Name''Of_Name X$ Deck/Dollars="The End" X$ Exit XThe End X$ Say F$FAO("SHAR-file ''Shar_File' was written in !SL part!%S",- X F$Integer(nParts)) X$ Directory/Size=Used/Date=Created 'Shar_File'* X$ Verify=F$Verify(Verify) $ GoSub Conve. . ./Dolingl