home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / txtut122.zip / textutil / src / sum.c < prev    next >
C/C++ Source or Header  |  1998-04-11  |  6KB  |  268 lines

  1. /* sum -- checksum and count the blocks in a file
  2.    Copyright (C) 86, 89, 91, 95, 1996 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  17.  
  18. /* Like BSD sum or SysV sum -r, except like SysV sum if -s option is given. */
  19.  
  20. /* Written by Kayvan Aghaiepour and David MacKenzie. */
  21.  
  22. #include <config.h>
  23.  
  24. #include <stdio.h>
  25. #include <sys/types.h>
  26. #include <getopt.h>
  27. #include "system.h"
  28. #include "error.h"
  29.  
  30. int safe_read ();
  31.  
  32. /* The name this program was run with. */
  33. char *program_name;
  34.  
  35. /* Nonzero if any of the files read were the standard input. */
  36. static int have_read_stdin;
  37.  
  38. /* Right-rotate 32-bit integer variable C. */
  39. #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x8000; else (c) >>= 1;
  40.  
  41. /* If nonzero, display usage information and exit.  */
  42. static int show_help;
  43.  
  44. /* If nonzero, print the version on standard output then exit.  */
  45. static int show_version;
  46.  
  47. static struct option const longopts[] =
  48. {
  49.   {"sysv", no_argument, NULL, 's'},
  50.   {"help", no_argument, &show_help, 1},
  51.   {"version", no_argument, &show_version, 1},
  52.   {NULL, 0, NULL, 0}
  53. };
  54.  
  55. static void
  56. usage (int status)
  57. {
  58.   if (status != 0)
  59.     fprintf (stderr, _("Try `%s --help' for more information.\n"),
  60.          program_name);
  61.   else
  62.     {
  63.       printf (_("\
  64. Usage: %s [OPTION]... [FILE]...\n\
  65. "),
  66.           program_name);
  67.       printf (_("\
  68. Print checksum and block counts for each FILE.\n\
  69. \n\
  70.   -r              defeat -s, use BSD sum algorithm, use 1K blocks\n\
  71.   -s, --sysv      use System V sum algorithm, use 512 bytes blocks\n\
  72.       --help      display this help and exit\n\
  73.       --version   output version information and exit\n\
  74. \n\
  75. With no FILE, or when FILE is -, read standard input.\n\
  76. "));
  77.       puts (_("\nReport bugs to textutils-bugs@gnu.ai.mit.edu"));
  78.     }
  79.   exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
  80. }
  81.  
  82. /* Calculate and print the rotated checksum and the size in 1K blocks
  83.    of file FILE, or of the standard input if FILE is "-".
  84.    If PRINT_NAME is >1, print FILE next to the checksum and size.
  85.    The checksum varies depending on sizeof(int).
  86.    Return 0 if successful, -1 if an error occurs. */
  87.  
  88. static int
  89. bsd_sum_file (const char *file, int print_name)
  90. {
  91.   register FILE *fp;
  92.   register unsigned long checksum = 0; /* The checksum mod 2^16. */
  93.   register long total_bytes = 0; /* The number of bytes. */
  94.   register int ch;        /* Each character read. */
  95.  
  96.   if (!strcmp (file, "-"))
  97.     {
  98.       fp = stdin;
  99.       have_read_stdin = 1;
  100.     }
  101.   else
  102.     {
  103.       fp = fopen (file, "r");
  104.       if (fp == NULL)
  105.     {
  106.       error (0, errno, "%s", file);
  107.       return -1;
  108.     }
  109.     }
  110.  
  111.   while ((ch = getc (fp)) != EOF)
  112.     {
  113.       total_bytes++;
  114.       ROTATE_RIGHT (checksum);
  115.       checksum += ch;
  116.       checksum &= 0xffff;    /* Keep it within bounds. */
  117.     }
  118.  
  119.   if (ferror (fp))
  120.     {
  121.       error (0, errno, "%s", file);
  122.       if (strcmp (file, "-"))
  123.     fclose (fp);
  124.       return -1;
  125.     }
  126.  
  127.   if (strcmp (file, "-") && fclose (fp) == EOF)
  128.     {
  129.       error (0, errno, "%s", file);
  130.       return -1;
  131.     }
  132.  
  133.   printf ("%05lu %5ld", checksum, (total_bytes + 1024 - 1) / 1024);
  134.   if (print_name > 1)
  135.     printf (" %s", file);
  136.   putchar ('\n');
  137.  
  138.   return 0;
  139. }
  140.  
  141. /* Calculate and print the checksum and the size in 512-byte blocks
  142.    of file FILE, or of the standard input if FILE is "-".
  143.    If PRINT_NAME is >0, print FILE next to the checksum and size.
  144.    Return 0 if successful, -1 if an error occurs. */
  145.  
  146. static int
  147. sysv_sum_file (const char *file, int print_name)
  148. {
  149.   int fd;
  150.   unsigned char buf[8192];
  151.   register int bytes_read;
  152.   register unsigned long checksum = 0;
  153.   long total_bytes = 0;
  154.  
  155.   if (!strcmp (file, "-"))
  156.     {
  157.       fd = 0;
  158.       have_read_stdin = 1;
  159.     }
  160.   else
  161.     {
  162.       fd = open (file, O_RDONLY);
  163.       if (fd == -1)
  164.     {
  165.       error (0, errno, "%s", file);
  166.       return -1;
  167.     }
  168.     }
  169.  
  170.   while ((bytes_read = safe_read (fd, buf, sizeof buf)) > 0)
  171.     {
  172.       register int i;
  173.  
  174.       for (i = 0; i < bytes_read; i++)
  175.     checksum += buf[i];
  176.       total_bytes += bytes_read;
  177.     }
  178.  
  179.   if (bytes_read < 0)
  180.     {
  181.       error (0, errno, "%s", file);
  182.       if (strcmp (file, "-"))
  183.     close (fd);
  184.       return -1;
  185.     }
  186.  
  187.   if (strcmp (file, "-") && close (fd) == -1)
  188.     {
  189.       error (0, errno, "%s", file);
  190.       return -1;
  191.     }
  192.  
  193.   printf ("%lu %ld", checksum % 0xffff, (total_bytes + 512 - 1) / 512);
  194.   if (print_name)
  195.     printf (" %s", file);
  196.   putchar ('\n');
  197.  
  198.   return 0;
  199. }
  200.  
  201. int
  202. main (int argc, char **argv)
  203. {
  204.   int errors = 0;
  205.   int optc;
  206.   int files_given;
  207.   int (*sum_func) () = bsd_sum_file;
  208.  
  209.  
  210. #ifdef __EMX__
  211. _wildcard(&argc, &argv);
  212. #endif
  213.  
  214.  
  215.   program_name = argv[0];
  216. #ifndef __EMX__
  217.   setlocale (LC_ALL, "");
  218.   bindtextdomain (PACKAGE, LOCALEDIR);
  219.   textdomain (PACKAGE);
  220. #endif
  221.   have_read_stdin = 0;
  222.  
  223.   while ((optc = getopt_long (argc, argv, "rs", longopts, (int *) 0)) != -1)
  224.     {
  225.       switch (optc)
  226.     {
  227.     case 0:
  228.       break;
  229.  
  230.     case 'r':        /* For SysV compatibility. */
  231.       sum_func = bsd_sum_file;
  232.       break;
  233.  
  234.     case 's':
  235.       sum_func = sysv_sum_file;
  236.       break;
  237.  
  238.     default:
  239.       usage (1);
  240.     }
  241.     }
  242.  
  243.   if (show_version)
  244.     {
  245.       printf ("sum (%s) %s\n", GNU_PACKAGE, VERSION);
  246.       exit (EXIT_SUCCESS);
  247.     }
  248.  
  249.   if (show_help)
  250.     usage (0);
  251.  
  252.   files_given = argc - optind;
  253.   if (files_given == 0)
  254.     {
  255.       if ((*sum_func) ("-", files_given) < 0)
  256.     errors = 1;
  257.     }
  258.   else
  259.     for (; optind < argc; optind++)
  260.       if ((*sum_func) (argv[optind], files_given) < 0)
  261.     errors = 1;
  262.  
  263.   if (have_read_stdin && fclose (stdin) == EOF)
  264.     error (EXIT_FAILURE, errno, "-");
  265.   exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
  266. }
  267.  
  268.