From:	CSBVAX::MRGATE!@KL.SRI.Com:BOB%HOWARD@cc.utah.edu@SMTP 13-SEP-1987 06:22
To:	EVERHART
Subj:	checksum/verify program (1 of 4)

Received: from CC.UTAH.EDU by KL.SRI.COM with TCP; Sun 13 Sep 87 02:34:25-PDT
Date: Sun, 13 Sep 87 03:36 MST
From: BOB%HOWARD@cc.utah.edu
Subject: checksum/verify program (1 of 4)
To: info-vax@KL.SRI.COM
X-VMS-To: INFOVAX


Here is the checksum/verify routine that I promised everyone a few months
ago. Sorry it took so long to get around to sending it.

There are 4 parts to the distribution, put them together and execute the
command procedure. Then you will find a file BUILD_CKSVER.COM. Execute 
this command procedure and it will build you a file CKSVER010.A which
can be installed with VMSINSTAL. 

Even if you don't want the checksum/verify program, there is a really nice 
generic set of VMSINSTAL command procedures called KITBUILD.COM and 
KITDATA.COM written here at HHMI. If there is some interest in more 
information about our VMSinstal procedures send me mail. If there is 
enough interest in it I will post the complete set of utilities to generate
VMSinstal savesets.

Bob Wheeler
Howard Hughes Medical Institute at Salt Lake City

Special thanks to Michael Bednarek for his very nice utility VMS_SHAR.


........................ Cut between dotted lines and save ......................
$!..............................................................................
$! VAX/VMS archive file created by VMS_SHAR V-4.03 05-Aug-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 BOB
$!      on Sunday 13-SEP-1987 02:31:57.91
$!
$! ATTENTION: To keep each article below 15872 bytes, this program
$!            has been transmitted in 4 parts.
$! You should concatenate ALL parts to ONE file and execute (@) that file.
$!
$! It contains the following 7 files:
$! BUILD_CKSVER.COM CHECKSUM.C CHECKSUM.RNH KITDATA.DAT KITINSTAL.COM TYPEDEFS.H
$! VERIFY.C
$!==============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ 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/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
        VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set (Output_File,b,o);
Position (Beginning_of(b));Loop x:=Erase_Character(1); Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;Move_Horizontal
(-Current_Offset);EndLoop;Move_Vertical(1);ExitIf Mark(None)=End_of(b)
EndLoop;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="BUILD_CKSVER.COM"
$ Check_Sum_is=503520738
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X$ cc checksum
X$ link checksum,sys$input/opt
Xsys$share:vaxcrtl.exe/share
X$
X$ cc verify
X$ link verify,sys$input/opt
Xsys$share:vaxcrtl.exe/share
X$
X$ runoff checksum.rnh
X$
X$ backup/log checksum.c,checksum.exe,verify.c,verify.exe,-
Xtypedefs.h,checksum.rnh,checksum.hlp,kitdata.dat,kitinstal.com -
Xcksver010.a/save
X$
X$ exit
$ GoSub Convert_File
$ File_is="CHECKSUM.C"
$ Check_Sum_is=118773976
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
XCHECKSUM / VERIFY
X
X  Computes a checksum for a file or files.  These checksums are often used
X  with the VERIFY command to verify that files have not been changed since
X  the checksum was performed.
X
X  Format:
X
X    CHECKSUM [filespec1] [filespec2]
X    VERIFY   [filespec2] [filespec3]
X
X  Filespec1 determins which files are to be checksummed.  Wildcards and full
X  pathnames are allowed.  If the filespec is not given on the command line
X  you will be prompted for it.  This filespec is required.
X
X  Filespec2 specifies the name of an optional output file for the checksums
X  or required input file for the VERIFY command.  No wildcards are allowed. 
X  If the filespec is not given on the command line you will be prompted for it.
X  The CHECKSUM command will send its output to stdio if you press return at
X  this prompt.
X  
X  Filespec3 specifies an optional output file for the VERIFY command.  If
X  the filespec is not given on the command line you will be prompted for it.
X  The VERIFY command will send its output to stdio if you press return at
X  this prompt.
X
X
X  Example:
X
X   CHECKSUM *.* FOO.CKS
X   VERIFY FOO.CKS
X
X  The example above checksums all files in the current directory and writes
X  the results to FOO.CKS.  These checksums are then verified against the
X  current files by using the VERIFY command which writes its verifications
X  to stdio.
X
X  If you want to verify files against those in another directory you
X  must edit the pathnames in the checksum file (FOO.CKS in the example.)
X
X  Note:
X
X    Directories and multiple versions of files are not checksummed.
X  
X*/
X
X
X
X
X#include <stdio.h>
X#include <descrip.h>
X#include <rmsdef.h>
X#include "typedefs.h"
X
X#define max_spec_chars 80
X
Xstatic struct dsc$descriptor_s search_file;
Xstatic struct dsc$descriptor_s result_file;
Xstatic u_long context;
Xstatic u_byte search_filename[max_spec_chars];
Xstatic u_byte result_filename[max_spec_chars];
X
X
X/**************************************************************************/
X/*                                                                        */
X/*        START_FILE_SEARCH() - INITIALIZE FOR A FILE SEARCH.             */
X/*                                                                        */
X/**************************************************************************/
X
Xvoid start_file_search(filespec, size)
X     u_byte *filespec;
X     u_word size;
X{
X
X  (void) strcpy(search_filename, filespec);
X
X  search_file.dsc$w_length = (u_word) strlen(search_filename);
X  search_file.dsc$a_pointer = &search_filename;
X  result_file.dsc$a_pointer = &result_filename;
X  result_file.dsc$w_length = max_spec_chars;
X
X  context = 0;
X}
X
X
X
X
X
X
X/**************************************************************************/
X/*                                                                        */
X/*  FINDFILE() - PARSE A WILDCARD FILE SPECIFICATION AND RETURN           */
X/*              FULL FILE SPECIFICATION.                                  */
X/*                                                                        */
X/**************************************************************************/
X
Xu_byte findfile(filespec)
X     u_byte *filespec;
X{
X
X  u_byte *p;
X  u_byte *q;
X  u_long status;
X  u_long lib$find_file();
X
X  status = lib$find_file(&search_file, &result_file, &context);
X
X  if (status == RMS$_NMF)
X    {
X      (void) lib$find_file_end(&context);
X      return(0);
X    }
X  else
X    if (status == RMS$_NORMAL)
X      {
X        p = &result_filename;
X        q = filespec;
X
X        while (*p != ' ')
X          *q++ = *p++;
X
X        *q = '\0';
X        return(1);
X      }
X    else
X      return(0);
X}
X
X
X
X
X
X/*********************************************************************/
X/*                                                                   */
X/*                      NOT_DIRECTORY()                              */
X/*                                                                   */
X/* RETURN 1 IF filespec IS NOT A DIRECTORY, ELSE RETURN 0.           */
X/*                                                                   */
X/*********************************************************************/
X
Xs_word not_directory( filespec )
Xu_byte *filespec;
X{
X  s_word i;
X
X  if(( filespec[0] == '\0' ) ||
X     ( filespec[1] == '\0' ) ||
X     ( filespec[2] == '\0' ) ||
X     ( filespec[3] == '\0' )) return(1);
X
X  i = 0;
X  while ( filespec[i+4] != '\0' ) {
X   if((  filespec[i]   == '.' ) &&
X      (( filespec[i+1] == 'D' ) || ( filespec[i+1] == 'd' )) &&
X      (( filespec[i+2] == 'I' ) || ( filespec[i+2] == 'i' )) &&
X      (( filespec[i+3] == 'R' ) || ( filespec[i+3] == 'r' )))
X     return(0);
X   else i++;
X }
X  return(1);
X}
X
X
X
X
X/**************************************************************************/
X/*                                                                        */
X/*                           MAIN                                         */
X/*                                                                        */
X/**************************************************************************/
X
X
Xmain(argc, argv)
Xs_word argc;
Xu_byte *argv[];
X{
X  FILE *fp, *out_fp;
X  u_byte findfile();
X  u_byte filespec[max_spec_chars];
X  u_byte last_filespec[max_spec_chars];
X  u_byte users_filespec[max_spec_chars];
X  u_byte outfile[max_spec_chars];
X  u_word write_to_file;           /* BOOLEAN */
X  u_word files_on_com_line;       /* BOOLEAN */
X  register u_word sum;            /* CHECKSUM */
X  register u_word i;              /* PLAIN'OL i */
X  register s_word dots;           /* DOT CHARACTERS FOR FORMATED OUTPUT */
X
X  /* INITIALIZE SOME STUFF */
X
X  files_on_com_line = FALSE;
X  write_to_file     = FALSE;
X  outfile[0]        = '\0';
X  users_filespec[0] = '\0';
X  last_filespec[0]  = '\0';
X
X
X  if( argc > 3 ) {
X    fprintf(stderr,"To many command line arguments.\n");
X    goto bail_out;
X  }
X
X  if( argc > 1) {                        /* GET FILESPEC IF ON COMMAND LINE */
X    files_on_com_line = TRUE;
X    strcpy(&users_filespec, argv[1]);
X  }
X
X  if( argc == 3) {                       /* GET OUTPUT FILE IF ON COM LINE */
X    write_to_file = TRUE;
X    strcpy(&outfile, argv[2]);
X  }
X  
X  if( !files_on_com_line ) {             /* GET FROM USER IF NOT ON COM LINE */
X    while ( users_filespec[0] == '\0' ) {
X      printf("File         : ");
X      gets  (users_filespec);
X    }
X    printf("Output file  : ");
X    gets  (outfile);
X    printf("\n\n");
X  }
X
X  /* IF AN OUTPUT FILE WAS SPECIFIED THEN SET A FLAG AND OPEN THE FILE */
X
X  if (outfile[0] != '\0') {
X    write_to_file = TRUE;
X    if ( (out_fp = fopen(outfile, "w")) == NULL) {
X      fprintf(stderr,"Can't open %s\n",outfile);
X      goto bail_out;
X    }
X  }
X
X
X  /* COMPUTE CHECKSUM FOR EACH FILE MATCHING USERS_FILESPEC */
X
X  start_file_search(users_filespec);
X  while(findfile(filespec))
X    {
X
X      /* IF IT'S NOT A DIRECTORY THEN GO AHEAD ELSE SKIP THIS FILESPEC */
X
X      if ( not_directory( filespec ))  {
X
X        /* GET RID OF VERSION NUMBERS */
X
X        i = 0;
X        while( filespec[ i++ ] != ';');
X        filespec[ --i ] = '\0';
X
X        /* IF THIS FILESPEC = THE LAST FILESPEC THEN IT'S TRYING */
X        /* TO WORK WITH A FILE THAT DOES NOT HAVE THE HIGHEST VERSION */
X        /* NUMBER SO JUST SKIP IT */
X
X        if( strcmp(last_filespec, filespec) ) {
X          strcpy(last_filespec, filespec);
X
X          /* OPEN THE FILE AND CHECKSUM IT */
X
X          if ( (fp = fopen(filespec, "r")) != NULL) {
X            sum = 1;
X            while ( !( feof(fp))){                 /* WHILE NOT EOF */
X              sum += (unsigned) fgetc(fp);         /* READ A CHARACTER */
X              if (sum & 0X8000) {                  /* ROTATE IF HIGH BIT SET */
X                sum <<= 1;
X                sum++;
X              }
X              else
X                sum <<= 1;                         /* ELSE JUST SHIFT */
X            }
X            
X            fclose(fp);
X            
X            /* WRITE THE FILESPEC AND CHECKSUM TO FILE OR STDOUT */
X
X            if (write_to_file) {
X
X              fprintf(out_fp,"%s",filespec);
X              dots = 70 - strlen(filespec);
X              if (dots > 0) for(i=1; i<dots; i++) fprintf(out_fp,"%c",'.'); 
X              fprintf(out_fp,"  ");
X              fprintf(out_fp,"%8u\n",sum);
X              
X            }
X            else {
X
X              printf("%s",filespec);
X              dots = 70 - strlen(filespec);
X              if (dots > 0) for(i=1; i<dots; i++) printf("%c",'.'); 
X              printf("  ");
X              printf("%8u\n",sum);
X              
X            }
X
X          }/* IF YOU CAN OPEN IT */
X        }/* IF IT'S NOT THE SAME FILE WITH A LOWER VERSION NUMBER */
X      }/* IF IT'S NOT A DIRECTORY */
X    }/* WHILE MORE FILES TO CHECKSUM */
X
X
Xif (write_to_file) fclose(out_fp);
Xbail_out:;
X}
$ GoSub Convert_File
$ File_is="CHECKSUM.RNH"
$ Check_Sum_is=1783449126
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X.lm2.rm70
X.i-2
X1 Checksum-Verify
X.bl
XComputes a checksum for a file or files.  These checksums are often used
Xwith the VERIFY command to verify that files have not been changed since
Xthe checksum was performed. Directories and multiple versions of files are 
Xnot checksummed.
X.bl
XFormat:
X.bl.i5
XCHECKSUM [filespec1] [filespec2]
X.i5
XVERIFY   [filespec2] [filespec3]
X.bl.i-2
X2 Qualifiers
X.bl.i5
XCHECKSUM [filespec1] [filespec2]
X.i5
XVERIFY   [filespec2] [filespec3]
X.bl
XFilespec1 specifies which files are to be checksummed.  Wildcards and full
Xpathnames are allowed.  This filespec is required, if the filespec is not
Xgiven on the command line you will be prompted for it.
X.bl
XFilespec2 specifies the name of an optional output file for the checksums
Xand required input file for the VERIFY command.  No wildcards are allowed. 
XIf the filespec is not given on the command line you will be prompted for it.
XThe CHECKSUM command will send its output to stdio if you press return at
Xthis prompt.
X.bl  
XFilespec3 specifies an optional output file for the VERIFY command.  If
Xthe filespec is not given on the command line you will be prompted for it.
XThe VERIFY command will send its output to stdio if you press return at
Xthis prompt.
X.bl1.i-2
X2 Example
X.bl.i5
XCHECKSUM *.* FOO.CKS
X.br.i5
XVERIFY FOO.CKS
X.bl
XThe example above checksums all files in the current directory and writes
Xthe results to FOO.CKS.  These checksums are then verified against the
Xcurrent files by using the VERIFY command which writes its verifications
Xto stdio.
X.bl
XIf the files are moved to another directory then the checksum file
X(FOO.CKS) should be edited to correct the pathnames before the
XVERIFY command is used.
X
$ GoSub Convert_File
$ File_is="KITDATA.DAT"
$ Check_Sum_is=1685414679
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X! KITDATA.DAT - Information needed to instal product
X!
X
X        p$name                  "CKSVER"
X        p$version               "010"
X
X        p$standard_directory    "sys$sysroot:[checksum]"
X
X        p$vms_version           "044"
X        p$peak_utilization      100
X        p$net_utilization       50
X
X        p$source_size           50
X
X
X.DIRECTORIES
X
X!       subdirectory    condition
X!       ------------    ---------
X
X        [.sources]      p$sources
X
X
X.SAVESET A
X
X!       final           file                    condition       special
X!       directory
X!       ----------      -----------             ----------      ----------
X
X        none            checksum.hlp            p$help          system_help
X        []              checksum.hlp            .not.p$help     system_help
X
X        sysmgr          cksver_login.com        p$required      system_login
X
X        []              checksum.exe            p$required
X        []              verify.exe              p$required
X
X        [.sources]      checksum.c              p$sources
X        [.sources]      verify.c                p$sources
X        [.sources]      typedefs.h              p$sources
X        [.sources]      checksum.rnh            p$sources
X
X.END
$ GoSub Convert_File
$ Goto Part3
