[comp.os.vms] checksum/verify program

BOB%HOWARD@CC.UTAH.EDU (09/13/87)

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

BOB%HOWARD@CC.UTAH.EDU (09/13/87)

$Part3:
$ File_is="KITINSTAL.COM"
$ Check_Sum_is=1362976760
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X$! Module:      CHECKSUM/VERIFY Installation Procedure for VMSINSTAL
X$!
X$! Author:      Bob Wheeler
X$!              Howard Hughes Medical Institute at Salt Lake City
X$
X$
X$       if f$ext(0,5,p1) .eqs. "HELP_" then goto 'p1
X$       if p1 .eqs. "VMI$_INSTALL" then goto install
X$       if p1 .eqs. "VMI$_IVP" then goto ivp
X$       exit vmi$_unsupported
X$
X$
X$  install:
X$       on control_y then vmi$callback control_y
X$       on warning then goto failed
X$
X$       say := write sys$output
X$
X$       p$required = 1
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  GET PARAMETERS  -  Read in symbols and values from KITDATA.DAT and equate
X$!                     them.
X$!
X$!------------------------------------------------------------------------------
X$
X$       open/read/error=kitdata_error k$kitdata vmi$kwd:kitdata.dat
X$
X$       k$line = 0
X$
X$  next_symbol:
X$
X$       k$rec = ""
X$
X$  read_loop_1:
X$
X$       read/end=kitdata_eof k$kitdata k$string
X$       k$line = k$line + 1
X$       k$string = f$edit(k$string,"UNCOMMENT,COMPRESS,TRIM")
X$
X$       k$rec = k$rec + k$string
X$       if k$rec .eqs. "" then goto read_loop_1
X$       if f$extract(f$length(k$rec) - 1,1,k$rec) -
X        .nes. "-" then goto assign_value
X$
X$       k$rec == f$extract(0,f$length(k$rec) - 1,k$rec)
X$       goto read_loop_1
X$
X$
X$  assign_value:
X$
X$       if f$extract(0,1,k$rec) .eqs. "." then goto check_vms
X$
X$       param = f$edit(f$element(0," ",k$rec),"TRIM")
X$       value = f$edit(f$element(1," ",k$rec),"TRIM")
X$
X$       if param .eqs. "" .or. value .eqs. "" then goto bad_sym_syntax
X$
X$       'param = 'value
X$       
X$       goto next_symbol
X$
X$
X$  bad_sym_syntax:
X$
X$       vmi$callback MESSAGE s BADPARAM -
X        "Invalid parameter assignment in KITDATA.DAT line ''k$line "
X$       say "    ''k$rec "
X$
X$       goto failed
X$
X$
X$  kitdata_error:
X$
X$       vmi$callback MESSAGE s nokitdata "KITDATA.DAT file not found"
X$       exit vmi$_failure
X$
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  CHECK VMS  -  Make sure that we are running the correct version of VMS
X$!
X$!------------------------------------------------------------------------------
X$
X$  check_vms:
X$
X$
X$       if f$type(p$vms_version) .nes. "" then goto version_known
X$
X$       vmi$callback MESSAGE s NOVERSION -
X    "Minimum version of VMS not supplied in symbol p$vms_version"
X$
X$       goto failed
X$
X$
X$  version_known:
X$
X$       say "" 
X$       if f$elem(0,",",vmi$vms_version) .nes. "RELEASED" then goto check_alt
X$       if f$elem(1,",",vmi$vms_version) .ges. p$vms_version then goto check_alt
X$       k$pretty = f$str(f$int(f$ext(0,2,p$vms_version))) + "." + -
X                 f$ext(2,1,p$vms_version)
X$       vmi$callback MESSAGE e badvms -
X                "''p$name requires VMS V''k$pretty or a later version."
X$       goto failed
X$
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  GET DIRECTORY - Figure out where the party is going to be
X$!
X$!------------------------------------------------------------------------------
X$
X$  check_alt:
X$
X$!      We don't want to deal with the problems of alternate roots.
X$
X$       if .not. vmi$alternate_root then goto get_dir
X$       vmi$callback MESSAGE e noaltroot -
X            "''p$name cannot be installed in an alternate system root."
X$       goto failed
X$
X$
X$  get_dir:
X$
X$!      Determine the directory in which the product is to be placed and create
X$!      the directory.
X$
X$       if f$type(p$standard_directory) .nes. "" then goto dir_known
X$
X$       vmi$callback MESSAGE s NODEFDIR -
X    "Default product directory not found in symbol p$standard_directory"
X$       goto failed
X$
X$
X$  dir_known:
X$
X$       vmi$callback ASK k$product_dir -
X                "In which directory is ''p$name to be installed" -
X                'p$standard_directory sd "@vmi$kwd:kitinstal HELP_NEW_DIR"
X$
X$       k$dir = f$parse(k$product_dir,,,"DEVICE","SYNTAX_ONLY") - 
X                + f$parse(k$product_dir,,,"DIRECTORY","SYNTAX_ONLY")
X$
X$       vmi$callback ASK k$ -
X                "Is directory ''k$dir correct" "YES" b
X$       if .not. k$ then goto get_dir
X$
X$       k$product_dir = k$dir
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  GET SOURCES -  See if there are sources and if the user wants them
X$!
X$!------------------------------------------------------------------------------
X$
X$  get_sources:
X$
X$       vmi$callback ASK p$sources -
X          "Do you want the VAX C sources for CHECKSUM/VERIFY installed" -
X          "YES" bd
X$
X$
X$       if .not.p$sources then goto do_help
X$
X$       p$peak_utilization = p$peak_utilization + p$source_size
X$       p$net_utilization = p$net_utilization + p$source_size
X$
X$

BOB%HOWARD@CC.UTAH.EDU (09/13/87)

X$!------------------------------------------------------------------------------
X$!
X$!  DCL and HELP - See if we can mess with the DCL tables and Help library
X$!
X$!------------------------------------------------------------------------------
X$
X$  do_help:
X$
X$       vmi$callback ASK p$help -
X          "Do you want the help files added to the system help library" -
X          "YES" bd
X$
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  PURGE - Find out if the user wants to purge old files
X$!
X$!------------------------------------------------------------------------------
X$
X$       say " "
X$       vmi$callback SET PURGE ask
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  SET IVP - Disable any IVP
X$!
X$!------------------------------------------------------------------------------
X$
X$       vmi$callback SET IVP no
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  ALL DONE - Tell him that were done asking questions
X$!
X$!------------------------------------------------------------------------------
X$
X$       say ""
X$       say ""
X$       say -
V   "    All of the questions for the installation of CHECKSUM/VERIFY have been 
Xasked."
X$       say "    The installation is continuing..."
X$       say ""
X$
X$!------------------------------------------------------------------------------
X$!
X$!  CHECK DISK - See if there is enough disk space 
X$!
X$!------------------------------------------------------------------------------
X$
X$       vmi$callback CHECK_NET_UTILIZATION k$ 'p$net_utilization
X$       if .not. k$ then vmi$callback MESSAGE e netblocks -
X             "''p$name requires ''p$net_utilization blocks after installation."
X$       if .not. k$ then goto failed
X$
X$       vmi$callback SET SAFETY conditional 'p$peak_utilization
X$       
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  BUILD LOGIN.COM - Build login.com file
X$!
X$!------------------------------------------------------------------------------
X$
X$       open/write k$temp vmi$kwd:cksver_login.com
X$
X$       write k$temp "$! cksver_login.com - system login.com file"
X$       write k$temp "$"
X$       write k$temp "$ check*sum  :== $''k$product_dir'checksum"
X$       write k$temp "$ ver*ify    :== $''k$product_dir'verify"
X$       write k$temp "$"
X$       write k$temp "$ exit"
X$
X$       close k$temp
X$
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  CREATE MAIN DIRECTORY - Create the main product directory
X$!
X$!------------------------------------------------------------------------------
X$
X$       if f$locate("SYS$SYSROOT",k$dir) .eqs. f$length(k$dir) then -
X                goto not_system_dir
X$
X$
X$       k$dir = f$parse(k$product_dir,,,"DIRECTORY","SYNTAX_ONLY") - "[" - "]"
X$       vmi$callback CREATE_DIRECTORY system 'k$dir
X$       goto get_subdir
X$
X$
X$  not_system_dir:
X$       vmi$callback CREATE_DIRECTORY user 'k$dir
X$
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  CREATE SUBDIRECTORIES - Create any subdirectories before we get into 
X$!                          safty mode.
X$!
X$!------------------------------------------------------------------------------
X$
X$  get_subdir:
X$
X$       if f$extract(0,12,k$rec) .nes. ".DIRECTORIES" then goto move_files
X$
X$
X$  create_dir:
X$
X$       k$rec = ""
X$
X$
X$  read_loop_2:
X$
X$       read/end=kitdata_eof k$kitdata k$string
X$       k$line = k$line + 1
X$       k$string = f$edit(k$string,"UNCOMMENT,COMPRESS,TRIM,UPCASE")
X$
X$       k$rec = k$rec + k$string
X$       if k$rec .eqs. "" then goto read_loop_2
X$       if f$extract(f$length(k$rec) - 1,1,k$rec) -
X        .nes. "-" then goto make_dir
X$
X$       k$rec == f$extract(0,f$length(k$rec) - 1,k$rec)
X$       goto read_loop_2
X$
X$  make_dir:
X$
X$       if f$extract(0,1,k$rec) .eqs. "." then goto move_files
X$
X$       k$subdir = f$edit(f$element(0," ",k$rec),"TRIM")
X$       k$cond = f$edit(f$element(1," ",k$rec),"TRIM")
X$
X$       if k$cond .nes. "" then goto cr_dir
X$
X$       vmi$callback MESSAGE s BADDIRSYN -
X        "Invalid of incomplete directory syntax in KITDATA.DAT line ''k$line "
X$       say "    ''k$rec "
X$       goto failed
X$
X$
X$  cr_dir:
X$
X$       if .not.'k$cond then goto create_dir
X$
X$       k$subdir = k$subdir - "["
X$       k$dir = k$product_dir - "]" + k$subdir
X$
X$       if f$locate("SYS$SYSROOT",k$dir) .eqs. f$length(k$dir) then -
X                goto not_sys_dir
X$
X$
X$       k$dir = f$parse(k$dir,,,"DIRECTORY","SYNTAX_ONLY") - "[" - "]"
X$       vmi$callback CREATE_DIRECTORY system 'k$dir
X$       goto create_dir
X$
X$
X$  not_sys_dir:
X$       vmi$callback CREATE_DIRECTORY user 'k$dir
X$
X$       goto create_dir
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  MOVE FILES  -  read in files from KITDATA.DAT and move them to the 
X$!                 right place.
X$!
X$!------------------------------------------------------------------------------
X$
X$  move_files:
X$
X$       open/write k$filelist vmi$kwd:filelist.txt
X$
X$       k$current_saveset = "A"
X$       k$saveset_loaded = 1
X$
X$
X$  get_next_file:
X$
X$       k$rec = ""
X$
X$  read_loop_3:
X$
X$       read/end=kitdata_eof k$kitdata k$string
X$       k$line = k$line + 1
X$       k$string = f$edit(k$string,"UNCOMMENT,COMPRESS,TRIM,UPCASE")
X$
X$       k$rec = k$rec + k$string
X$       if k$rec .eqs. "" then goto read_loop_3
X$       if f$extract(f$length(k$rec) - 1,1,k$rec) -
X        .nes. "-" then goto get_directive
X$
X$       k$rec == f$extract(0,f$length(k$rec) - 1,k$rec)
X$       goto read_loop_3
X$
X$  
X$  get_directive:
X$
X$!      show symbol k$rec
X$!      inquire keep "keep going"
X$!      if keep .nes. "" then set ver
X$
X$       if f$extract(0,4,k$rec) .nes. ".END" then goto check_saveset
X$
X$       close k$kitdata
X$       close k$filelist
X$
X$       vmi$callback FIND_FILE k$ vmi$root:[sysexe]sortmerge.exe "" s k$found
X$
X$       if k$found .eqs. "S" then -
X                sort vmi$kwd:filelist.txt vmi$kwd:filelist.txt
X$
X$       say ""
X$       say ""
X$       say -
X    "    Your VMS system will now be updated to include the following new and"
X$       say "    modified files: "
X$       say ""
X$       say ""
X$
X$       type vmi$kwd:filelist.txt
X$
X$       say ""
X$       say ""
X$
X$
X$       goto done_with_files
X$
X$
X$  check_saveset:
X$
X$       if f$extract(0,8,k$rec) .nes. ".SAVESET" then goto do_file
X$
X$       k$current_saveset = f$edit(f$element(1," ",k$rec),"TRIM")
X$       k$saveset_loaded = 0
X$
X$       if k$current_saveset .nes. "" then goto get_next_file
X$
X$       vmi$callback MESSAGE s BADSAVESET -
X        "Missing Saveset identification in KITDATA.DAT line ''k$line "
X$       say "    ''k$rec "
X$
X$       goto failed
X$
X$
X$  do_file:
X$
X$       k$final_dir = f$edit(f$element(0," ",k$rec),"TRIM")
X$       k$file = f$edit(f$element(1," ",k$rec),"TRIM")
X$       k$cond = f$edit(f$element(2," ",k$rec),"TRIM")
X$       k$special = f$edit(f$element(3," ",k$rec),"TRIM")
X$
X$       if k$cond .nes. "" then goto have_enough
X$
X$       vmi$callback MESSAGE s BADFILESPEC -
X        "Missing or incomplete file specification in KITDATA.DAT line ''k$line "
X$       say "    ''k$rec "
X$       goto failed
X$
X$
X$  have_enough:
X$
X$       if .not.'k$cond then goto get_next_file
X$
X$       if k$saveset_loaded then goto determine_dir
X$
X$       vmi$callback RESTORE_SAVESET 'k$current_saveset
X$       k$saveset_loaded = 1
X$
X$
X$  determine_dir:
X$
X$       if f$extract(0,1,k$final_dir) .nes. "[" then goto check_system_dir
X$
X$       k$sub_dir = k$final_dir - "[" - "]"
X$       k$final_dir = k$product_dir - "]" + k$sub_dir + "]"
X$       k$nice_dir = k$final_dir
X$
X$       goto check_special
X$
X$
X$  check_system_dir:
X$
X$       if k$final_dir .eqs. "NONE" then goto no_directory
X$
X$       K$SYS_DIRS = "SYSCBI SYSERR SYSEXE SYSHLP SYSLIB SYSMAINT" -
X        + " SYSMGR SYSMSG SYSTEST SYSUPD SYSHLP.EXAMPLES"
X$
X$       if f$locate(k$final_dir,k$sys_dirs) .ne. f$length(k$sys_dirs) -
X                then goto valid_system_dir
X$
X$       vmi$callback MESSAGE s BADSYSDIR -
X        "Invalid system directory specified in KITDATA.DAT line ''k$line "
X$       say "    ''k$cmd "
X$
X$       goto failed
X$
X$
X$  valid_system_dir:
X$
X$       k$sys_log = "SYS$INSTRUCTION SYS$ERRORLOG SYS$SYSTEM SYS$HELP " -
X        + "SYS$LIBRARY SYS$MAINTENANCE SYS$MANAGER SYS$MESSAGE " -
X        + "SYS$TEST SYS$UPDATE SYS$EXAMPLES"
X$
X$       k$i = -1
X$
X$  loop_start:
X$       k$i = k$i + 1
X$
X$       if f$element(k$i," ",k$sys_dirs) .nes. k$final_dir then -
X                goto loop_start
X$
X$       k$nice_dir = f$element(k$i," ",k$sys_log)
X$       k$final_dir = "vmi$root:[''k$final_dir]"
X$
X$       say ""
X$       vmi$callback MESSAGE i SYSFILE -
X        "    This product adds the file ''k$file to the "
X$       vmi$callback MESSAGE i SYSFILE -
X        "    system directory ''k$nice_dir "
X$       say ""
X$
X$       k$nice_dir = k$nice_dir + ":"
X$
X$       goto check_special
X$
X$
X$  no_directory:
X$
X$       k$final_dir = ""
X$
X$
X$  check_special:
X$
X$       if k$special .eqs. "" then goto move_it
X$
X$       if k$special .nes. "SYSTEM_DCL" then goto check_for_help
X$
X$       if k$final_dir .eqs. "" then goto update_dcl
X$
X$       say ""
X$       say "    The command for ''p$name will not be added to the system DCL"
X$       say "    tables. The file ''k$file is being placed in the "
X$       say "    directory ''k$final_dir and will have to be"
X$       say "    enabled with the SET COMMAND command at a later time."
X$       say ""
X$
X$       goto move_it
X$
X$
X$  update_dcl:
X$
X$       vmi$callback PROVIDE_DCL_COMMAND 'k$file
X$
X$       k$string = -
X        f$fao("    !50AS     [!AS]","SYS$LIBRARY:DCLTABLES.EXE","modified")
X$       write k$filelist k$string
X$
X$       goto get_next_file
X$
X$
X$  check_for_help:
X$
X$       if k$special .nes. "SYSTEM_HELP" then goto check_for_startup
X$
X$       if k$final_dir .eqs. "" then goto update_help
X$
X$       say ""
X$       say "    The help for ''p$name will not be added to the system help"
X$       say "    library. The file ''k$file is being placed in the "
X$       say "    directory ''k$final_dir and can be added to"
X$       say "    the system help files at a later time."
X$       say ""
X$
X$       goto move_it
X$
X$
X$  update_help:
X$
X$       vmi$callback PROVIDE_DCL_HELP 'k$file
X$
X$       k$string = -
X        f$fao("    !50AS     [!AS]","SYS$HELP:HELPLIB.HLB","modified")
X$       write k$filelist k$string
X$
X$       goto get_next_file
X$
X$
X$  check_for_startup:
X$
X$       if k$special .nes. "SYSTEM_STARTUP" then goto check_for_login
X$
X$       say ""
V$       say "    This product requires that the file ''k$file be included in th
Xe"
V$       say "    system startup file SYSTARTUP.COM so that it can be executed a
Xt"
X$       say "    system boot time."
X$       say ""
X$
X$       goto move_it
X$
X$
X$  check_for_login:
X$
X$       if k$special .nes. "SYSTEM_LOGIN" then goto bad_special
X$
X$       say ""
V$       say "    This product requires that the file ''k$file be included in th
Xe"
X$       say "    system login file SYLOGIN.COM so that it can be executed when"
X$       say "    users login to the system."
X$       say ""
X$
X$       goto move_it
X$
X$
X$  bad_special:
X$
X$       vmi$callback MESSAGE s BADSPECIAL -
X        "Unknown special file qualifier in KITDATA.DAT line ''k$line "
X$       say "    'k$rec "
X$
X$       goto failed
X$
X$
X$  move_it:
X$
X$       if f$locate("SYS$SYSROOT",k$final_dir) .nes. f$length(k$final_dir) -
X                then k$final_dir = "VMI$ROOT" + k$final_dir -"SYS$SYSROOT"
X$
X$
X$       if f$parse("''k$file'",,,"TYPE","SYNTAX_ONLY") .eqs. ".EXE" then -
X                goto move_image
X$
X$       vmi$callback PROVIDE_FILE k$ 'k$file 'k$final_dir
X$       goto update_list
X$
X$
X$  move_image:
X$
X$       vmi$callback PROVIDE_IMAGE k$ 'k$file 'k$final_dir
X$
X$
X$ update_list:
X$
X$       k$full = k$nice_dir + k$file
X$
X$       k$string = -
X        f$fao("    !50AS     [!AS]",k$full,"new")
X$       write k$filelist k$string
X$
X$
X$       if k$special .eqs. "SYSTEM_STARTUP" then -
X                vmi$callback SET STARTUP 'k$file
X$
X$       goto get_next_file
X$
X$
X$
X$  kitdata_eof:
X$
X$       vmi$callback MESSAGE s ENDOFFILE -
X                "KITDATA.DAT file missing .END directive"
X$
X$       goto failed
X$       exit vmi$_failure
X$
X$
X$  done_with_files:
X$
X$       exit vmi$_success
X$
X$
X$  failed:
X$       close k$kitdata
X$       close/error=null k$filelist
X$  null:
X$
X$       exit vmi$_failure
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  HELP - Entry point for help
X$!
X$!------------------------------------------------------------------------------
X$
X$
X$  HELP_NEW_DIR:
X$       type sys$input:
X    You must choose a directory in which CKSVER will be installed. The 
X    directory can reside on the system disk or any other disk which is 
X    permanently mounted.  By default, the product is installed in the
X    directory SYS$SYSROOT:[CHECKSUM].
X
X$       exit
X$
X$
X$
X$!------------------------------------------------------------------------------
X$!
X$!  IVP - If there is one
X$!
X$!------------------------------------------------------------------------------
X$
X$IVP:
X$       vmi$callbask MESSAGE i noivp
X           "CHECKSUM/VERIFY does not have an Installation Verification Program."
X$       exit vmi$_success
X$  exit
$ GoSub Convert_cbvax.Be y, y$  BO

BOB%HOWARD@CC.UTAH.EDU (09/13/87)

$Part4:
$ File_is="TYPEDEFS.H"
$ Check_Sum_is=958757556
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X  typedefs.h  -  type definitions
X*/
X
V#ifndef TYPEDEFS                                                     /* if we h
Xave not included typdefs then do it */
V#define TYPEDEFS                                                     /* define 
XTYPEDEFS to indicate they are defined */
X
Xtypedef unsigned int    u_int;
Xtypedef          int    s_int;
Xtypedef unsigned char   u_byte;
Xtypedef          char   s_byte;
Xtypedef unsigned short  u_word;
Xtypedef          short  s_word;
Xtypedef unsigned long   u_long;
Xtypedef          long   s_long;
Xtypedef          float  s_real;
Xtypedef          double d_real;
X
X#endif
$ GoSub Convert_File
$ File_is="VERIFY.C"
$ Check_Sum_is=436419089
$ 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#include <stdio.h>
X#include <descrip.h>
X#include <rmsdef.h>
X#include "typedefs.h"
X
X#define  out_of_chars -1
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
Xu_byte filespec[max_spec_chars];
Xu_byte infile[max_spec_chars];              /* FILENAME OF FILES TO VERIFY */
Xu_byte outfile[max_spec_chars];             /* FILENAME TO WRITE CHECKSUMS TO */
X
Xs_long old_checksum;
X
XFILE *fp, *in_fp, *out_fp;
X
X
X/**********************************************************************/
X/*                                                                    */
X/*                           GET_FILESPEC                             */
X/*                                                                    */
X/**********************************************************************/
X
Xs_word get_filespec()
X{
X  register s_word i;
X  u_byte buff;
X
X  /* READ FILE SPECIFICATION BY READING TO THE FIRST SPACE IN THE LINE. */
X  /* THEN SCAN BACKWARDS THROUGH THE CHARS  AND REPLACE DOTS WITH NULLS */
X
X  for( i=0; i<max_spec_chars ; i++) filespec[ i ] = '\0';
X  i = 0;
X  while((( filespec[ i++ ] = getc( in_fp ) ) != ' ') &&
X       (!feof( in_fp )));
X  if( feof( in_fp )) return(out_of_chars);
X
X  filespec[ --i ] = '\0'; /* GET RID OF SPACE */
X  while( filespec [ --i ] == '.') filespec[ i ] = '\0';
X
X
X  /* READ THE CHECKSUM */
X
X  fscanf(in_fp,"%d", &old_checksum);
X  while(( buff = getc( in_fp )) != '\n' );
X}
X
X
X
X
X
X
X/************************************************************************/
X/*                                                                      */
X/*                          MAIN                                        */
X/*                                                                      */
X/************************************************************************/
X
Xmain(argc, argv)
Xs_word argc;
Xu_byte *argv[];
X{
X
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  u_word write_to_file;            /* BOOLEAN */
X  u_word missing;                  /* BOOLEAN */
X  u_word files_on_com_line;        /* BOOLEAN */
X
X  u_byte buff;
X  s_long n_good;                   /* COUNT OF GOOD FILES */
X  s_long n_bad;                    /* COUNT OF BAD FILES */
X  s_long n_missing;                /* COUNT OF MISSING FILES */
X
X  /* INITIALIZE SOME STUFF */
X
X  n_good = n_bad = n_missing = 0;
X  files_on_com_line = FALSE;
X  write_to_file = FALSE;
X  outfile[0] = '\0';
X  infile[0] = '\0';
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 INPUT FILE IF ON COMMAND LINE */
X    files_on_com_line = TRUE;
X    strcpy(&infile, argv[1]);
X  }
X
X  if( argc == 3) {                /* GET OUTPUT FILE IF ON COMMAND LINE */
X    write_to_file = TRUE;
X    strcpy(&outfile, argv[2]);
X  }
X  
X
Xif( !files_on_com_line ) {        /* GET FROM USER IF NOT ON COMMAND LINE */
X
X  while ( infile[0] == '\0' ) {
X    printf("File         : ");
X    gets  (infile);
X  }
X  printf("Output file  : ");
X  gets  (outfile);
X  printf("\n\n");
X}
X
X  /* OPEN THE INPUT FILE */
X
X  if ( (in_fp = fopen(infile, "r")) == NULL) {
X    fprintf(stderr,"Can't open %s\n",infile);
X    goto bail_out;
X  }
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  /* FOR EACH FILE, IF YOU CAN OPEN IT THEN CHECKSUM IT ELSE SET missing */
X  /* TO TRUE. */
X
X      while ( get_filespec() != out_of_chars ) {
X
X        missing = FALSE;
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          fclose(fp);
X        }
X        else missing = TRUE;
X
X
X        /* IF OUTPUT IS TO A FILE... */
X
X        if (write_to_file) {
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          if (missing) {
X            fprintf(out_fp,"  Missing\n");
X            n_missing++;
X          }
X          else {
X            if (old_checksum == sum) {
X              fprintf(out_fp,"  Good\n");
X              n_good++;
X            }
X            else {
X              fprintf(out_fp,"  Bad\n");
X              n_bad++;
X            }
X          }
X        }
X        
X        /* IF OUTPUT IS TO STDOUT */
X        
X        else {
X          printf("%s",filespec);
X          dots = 70 - strlen(filespec);
X          if (dots > 0) for(i=1; i<dots; i++) printf("%c",'.'); 
X          if (missing) {
X            printf("  Missing\n");
X            n_missing++;
X          }
X          else {
X            if (old_checksum == sum) {
X              printf("  Good\n");
X              n_good++;
X            }
X            else {
X              printf("  Bad\n");
X              n_bad++;
X            }
X          }
X        }
X      }
X
X  if (write_to_file) {
X    fprintf(out_fp,"\n\n");
X    fprintf(out_fp,"                        ");
X    fprintf(out_fp,"Good     :  %d\n",n_good);
X    fprintf(out_fp,"                        ");
X    fprintf(out_fp,"Bad      :  %d\n",n_bad);
X    fprintf(out_fp,"                        ");
X    fprintf(out_fp,"Missing  :  %d\n",n_missing);
X    fclose(out_fp);
X  }
X  else {
X    printf("\n\n");
X    printf("                        ");
X    printf("Good     :  %d\n",n_good);
X    printf("                        ");
X    printf("Bad      :  %d\n",n_bad);
X    printf("                        ");
X    printf("Missing  :  %d\n",n_missing);
X  }
X
X bail_out:;
X}
$ GoSub Convert_File
$ Exit