123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /*
- * sum [file1] [file2] [file3] ...
- * sum utility written for GNU - checksum and count blocks in a file
- * Copyright (C) 1986 Kayvan Aghaiepour
- *
- * This program is distributed in the hope that it will be useful,
- * but without any warranty. No author or distributor
- * accepts responsibility to anyone for the consequences of using it
- * or for whether it serves any particular purpose or works at all,
- * unless he says so in writing.
- *
- * Everyone is granted permission to copy, modify and redistribute
- * this program, but only under the conditions described in the
- * document "GNU Emacs copying permission notice". An exact copy
- * of the document is supposed to have been given to you along with
- * GNU Emacs so that you can know how you may redistribute it all.
- * It should be in a file named COPYING. Among other things, the
- * copyright notice and this notice must be preserved on all copies.
- *
- */
- #include <stdio.h>
- /* macro to right-rotate an integer variable */
- #define ROTATE(c) if ((c) & 01) (c) = ((c) >>1) + 0x8000; else (c) >>= 1;
- main (argc, argv)
- int argc;
- char **argv;
- {
- int error;
- error = 0;
- switch (argc)
- {
- case 1: /* no arguments */
- if (sumfile (NULL, 0) < 0)
- {
- error += 10;
- }
- break;
- case 2: /* one argument */
- if (sumfile (argv[1], 0) < 0)
- {
- error += 10;
- }
- break;
- default: /* more than one argument */
- for (argc--, argv++; argc > 0; argc--, argv++)
- {
- if (sumfile (argv[0], 1) < 0)
- {
- error += 10;
- }
- }
- }
- return (error);
- }
- /*
- * sumfile does the checksum itself. Returns negative if something goes
- * wrong. Else, it returns non-negative and prints the desired information.
- */
- sumfile (s, printname)
- char *s; /* filename of file to check */
- int printname; /* boolean. print file name or not? */
- {
- register FILE *readfile; /* the file */
- register unsigned checksum; /* the checksum mod 2^16. */
- register long bytenum; /* the number of bytes. */
- register int ch; /* The character to read */
- if (s == NULL)
- {
- readfile = stdin; /* no arguments, so read from stdin */
- }
- else if ((readfile = fopen (s, "r")) == NULL)
- {
- perror_with_name (s); /* File inaccessible for some reason */
- return (-1);
- }
-
- checksum = 0;
- bytenum = 0;
- while ((ch = getc (readfile)) != EOF)
- {
- bytenum++;
- ROTATE (checksum);
- checksum += ch;
- checksum &= 0xffff; /* keep it within bounds */
- }
- if (ferror (readfile))
- { /* something bad has happened */
- perror_with_name (s);
- return (-1);
- }
- printf ("%05u%6ld", checksum, (bytenum + BUFSIZ - 1) / BUFSIZ);
- if (printname)
- printf (" %s\n", s);
- else
- putchar ('\n');
- fclose (readfile);
- return (1);
- }
- perror_with_name (name)
- char *name;
- {
- extern int errno, sys_nerr;
- extern char *sys_errlist[];
- char *s;
- if (errno < sys_nerr)
- fprintf (stderr, "%s for %s\n", name);
- else
- fprintf (stderr, "(Unknown error) cannot open %s", name);
- }
|