From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 10-MAR-1991 08:38:06.70
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	Checksum program -was anti-virus for VMS-part 2

Received:  by crdgw1.ge.com (5.57/GE 1.80)
	 id AA08932; Fri, 8 Feb 91 11:09:14 EST
Message-Id:  <9102081609.AA08932@crdgw1.ge.com>
Received: From SCFB.NWC.NAVY.MIL by CRVAX.SRI.COM with TCP; Fri,  8 FEB 91 07:44:00 PST
Date: 8 Feb 91 07:24:00 PDT
From: "FIDLER::LEVINE" <levine%fidler.decnet@scfb.nwc.navy.mil>
Subject: Checksum program -was anti-virus for VMS-part 2
To: "wlbaker" <wlbaker@relay.nswc.navy.mil>
Cc: "info-vax" <info-vax@crvax.sri.com>

-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
X;
X`09movl`09#number_of_crc,r11`09; set up loop count for total # of CRC's
X`09moval`09crc_poly,r10`09`09; start of polynomial table
X`09moval`09crc_tables,r9`09`09; start of table to store results
X10$:`09`09pushl`09r9`09`09; 2'n arg is addr to store result
X`09`09pushl`09r10`09`09; 1'st arg is addr of polynomial
X`09`09calls`09#2,g`5Elib$crc_table ; build table for polynomial
X`09`09addl2`09#4,r10`09`09; reset polynomial table to next entry
X`09`09addl2`09#<4*16>,r9`09; advance pointer to next table entry
X`09`09decl`09r11`09`09; dec CRC counter
X`09`09bgtr`0910$`09`09; if not done-loop back
X;`09when done-fall thorough to per command loop back point
X`09.page
X`09.subtitle`09start of per file check loop-get file name and open
X;
X;`09loop back point to read in a new file specification
X;`09which can contain wild cards. Program comes back to this
X;`09point only when all files matching input spec have been
X;`09checked
X;
Xfull_loop_back:
X;
X;`09get file name-exit if error or zero length
X;
X`09callg`09get_file_arg,g`5Elib$get_foreign
X`09blbs`09r0,1$
X`09cmpl`09#rms$_eof,r0`09;exit on <`5Ez>
X`09beql`095$`09`09;on eof-don't output error message
X`09$exit_s`09r0`09`09;some other error occoured-exit with value
X1$:`09tstw`09file_length`09;also zero length file name
X`09bneq`092$
X5$:`09$exit_s`09`09`09; take exit without error status
X2$:`09movl`09#1,force`09;subsequent passes-force prompt
X;
X;`09at the end of each file checked-the program comes back here
X;`09to see if any more files need to be checked due to wild cards
X;`09in the file spec.
X;
Xwild_card_loop_back:
X`09movc5`09#0,ff_string,#0,#1024,ff_string`09;clear string
X`09movl`09#1024,ff_length`09;reset length
X`09callg`09ff_arg,g`5Elib$find_file`09;scan for next file
X`09blbs`09r0,7$`09`09;no error-process next file
X`09cmpl`09#rms$_nmf,r0`09;check for found all files with matching name
X`09beql`096$`09`09;all files found
X`09cmpl`09#rms$_fnf,r0`09;check for none to find
X`09beql`099$
X`09$exit_s`09r0`09`09;all else kills with status
X9$:`09pushl`09r0`09`09;signal file not found
X`09calls`09#1,g`5Elib$signal
X6$:`09callg`09ffe_arg,g`5Elib$find_file_end`09;terminate find_file search
X`09blbc`09r0,8$`09`09; on error-take error exit
X`09brw`09full_loop_back`09;go get new file name
X8$:`09$exit_s`09r0`09`09;error exit with status
X7$:`09locc`09#`5Ea/ /,ff_length,ff_string`09;find length of file name
X`09subl2`09r0,ff_length
X;
X;`09Haveing found a file matching the specification- now
X;`09set up RMS control blocks for file access
X;
X`09$fab_store`09fab=fab,-
X`09`09`09fac=<bio,get>,-
X`09`09`09fna=ff_string,-
X`09`09`09fns=ff_length,-
X`09`09`09nam=nam,-
X`09`09`09shr=<put,get,del,upi,upd>
X`09$rab_store`09rab=rab,-
X`09`09`09fab=fab,-
X`09`09`09rac=seq,-
X`09`09`09rop=<bio,rah>
X`09$nam_store`09nam=nam,-
X`09`09`09esa=nam_work,-
X`09`09`09ess=#255,-
X`09`09`09rsa=nam_exp,-
X`09`09`09rss=#255
X`09$open`09fab=fab`09;open the file
X`09blbs`09r0,3$`09; if no error continue
X`09pushl`09r0`09; on access failure-signal problem and get next file
X`09calls`09#1,g`5Elib$signal
X`09brw`09wild_card_loop_back
X3$:`09$connect`09rab=rab`09;connect to open file
X`09blbs`09r0,4$`09; continue on no error
X`09pushl`09r0`09; on connect failure-close file,signal error-try again
X`09$close`09fab=fab
X`09calls`09#1,g`5Elib$signal
X`09brw`09wild_card_loop_back
X4$:
X;
X;`09file is now open-fall through to the setup for checks
X;
X`09.page
X`09.subtitle`09inital crc value, checksums
X;
X;`09reload current crc value tables with starting value
X;
X`09movc3`09#<number_of_crc*4>,crc_init,crc_value
X;
X;`09init checksum values
X;
X`09clrl`09checksum_8
X`09clrl`09checksum_16
X`09clrl`09checksum_32
X
X`09.page
X`09.subtitle`09read a block and set up r10,r11
X;
X;`09this section is the top of the loop to read a file
X;`09a chunk at a time for the check-after all checks are
X;`09complete on one chunk-come back here to get the next
X;
X;`09read up to 32 blocks from file
X;
X20$:`09movc5`09#0,io_buffer,#0,#16384,io_buffer;zero the buffer
X`09moval`09io_buffer,rab+rab$l_ubf`09`09;load buffer address
X`09movw`09#16384,rab+rab$w_usz`09`09;load buffer size
X`09$read`09rab=rab`09`09`09`09;read section of file into buff
X`09blbs`09r0,21$`09`09`09`09;on  no error-contine
X`09cmpl`09#rms$_eof,r0`09;on eof-done-go to final processing
X`09bneq`0922$
X`09brw`0950$
X22$:`09pushl`09r0`09`09;error-close file-log error and try again
X`09$close`09fab=fab
X`09calls`09#1,g`5Elib$signal`09; signal error to user
X`09brw`09wild_card_loop_back ;go get next file to check
X21$:`09moval`09io_buffer,r11`09;set up pointer to buffer
X`09movzwl`09rab+rab$w_rsz,r10`09;set up actual size of buffer read in
X
X`09.page
X`09.subtitle`09calc checksum s
X;
X;`09calc checksum-add 8,16,32 elements
X;
X;`09all adds are done in a 4 byte at a time loop. If the block
X;`09is not mod 2 or 4 in length, the rest of the buffer has been zeroed
X;`09so no effect on the checksum will occour.
X;
X`09movl`09r11,r9`09`09;make local copy of pointer
X`09movl`09r10,r8`09`09;and size count
X`09movl`09checksum_8,r7`09;load to registers for temp use`20
X`09movl`09checksum_16,r6`09;the current checksum values
X`09movl`09checksum_32,r5
X30$:`09`09addb2`090(r9),r7`09;do the byte checksum
X`09`09addb2`091(r9),r7
X`09`09addb2`092(r9),r7
X`09`09addb2`093(r9),r7
X`09`09addw2`090(r9),r6`09;do the word checksum
X`09`09addw2`092(r9),r6
X`09`09addl2`09(r9)+,r5`09;do the longword checksum & Update ptr
X`09`09subl2`09#4,r8`09;decrement the counter by 4 bytes
X`09`09bgtr`0930$`09;if not done-loop back
X`09movl`09r7,checksum_8`09;store the updated checksum's back in memory
X`09movl`09r6,checksum_16
X`09movl`09r5,checksum_32
X`09.page
X`09.subtitle`09set up and do each crc
X;
X;`09do all the CRC's
X;`09set up in a loop one crc at a time
X;`09with no need for user to add code when
X;`09new CRC is added
X;
X;`09set up loop counter, pointers for the per CRC loop
X;
X`09movl`09#number_of_crc,r9`09;number of crc's to calc
X`09moval`09crc_tables,r8`09`09;crc table
X`09moval`09crc_value,r7`09`09;current/inital crc value
X;
X;`09loop back point for one pass through per CRC specified
X;
X40$:`09`09crc`09(r8),(r7),r10,io_buffer`09;calc crc
X`09`09movl`09r0,(r7)+`09;save new crc value back to memory
X`09`09addl2`09#<4*16>,r8`09;jump pointer to next CRC table
X`09`09decl`09r9`09`09;dec crc counter
X`09`09bgtr`0940$`09`09;and if not done-loop back for next crc
X`09brw`0920$`09;partial CRC done-loop back for next block to process
X
X`09.page
X`09.subtitle`09close down file
X;
X;`09file has been completely processed-close down
X;
X50$:`09$close`09fab=fab
X
X`09.page
X`09.subtitle`09prepare results  and display them
X;
X;`09use SYS$FAO, build the output string then print it
X;
X;`09build on the stack the arguments to SYS$FAO in reverse order
X;
X`09movl`09#number_of_crc,r11`09;set up a loop to pushon the CRC's
X`09moval`09<crc_length+<number_of_crc*4>>,r10 ;addr of crc length table
X`09moval`09<crc_value+<number_of_crc*4>>,r9   ;addr of crc table
X;`09create FAO parameter stack
X;`09push on last to first
X;`09`09first push on crc values in reverse order
X60$:`09`09extzv`09#0,-4(r10),-4(r9),r0`09;extract only significant
X`09`09pushl`09r0`09`09`09;bits of CRC
X`09`09subl2`09#4,r10`09`09`09;backup one entry in length
X`09`09subl2`09#4,r9`09`09`09;and crc tables
X`09`09decl`09r11`09`09`09;dec counter
X`09`09bgtr`0960$`09`09`09;repeat if more crc's to go
X;`09next the checksums in reverse order
X`09pushl`09checksum_32
X`09movzwl`09checksum_16,-(sp)
X`09movzbl`09checksum_8,-(sp)
X;`09last the first arg(s)-the file  name
X;`09use the $NAM block to get only the file name,type and version.
X;`09the rest of the specification (node,device,directory)
X;`09is left off.
X`09movl`09nam+nam$l_name,-(sp)`09;get starting point of name
X`09addb3`09nam+nam$b_name,nam+nam$b_type,r0`09;calc len of name+type
X`09addb2`09nam+nam$b_ver,r0`09`09`09;+version
X`09movzbl`09r0,-(sp)`09`09;and store
X`09pushal`09output_buffer`09`09;output line buffer
X`09pushal`09output_length`09`09;resulting length goes here
X`09pushal`09format`09`09`09;address of format spec descripter
X;`09number of args
X;`09`093`09fao parameters-format str, output buff, output len
X;`09`092`09file name string
X;`09`093`09checksum's
X;`09`09x`09crc's
X`09calls`09#<3+2+3+number_of_crc>,g`5Esys$fao
X`09pushal`09output_length`09;the output length is also a descripter
X`09calls`09#1,g`5Elib$put_output`09;output results
X`09brw`09wild_card_loop_back`09;get new file to process
X`09.end`09check
$ CALL UNPACK CHECK.MAR;31 859094975
$ v=f$verify(v)
$ EXIT


