--- pgp/contrib/md5sum/md5sum.c 2018/04/24 16:39:49 1.1.1.2 +++ pgp/contrib/md5sum/md5sum.c 2018/04/24 16:45:03 1.1.1.3 @@ -1,243 +1,259 @@ -/* - * md5sum.c - Generate/check MD5 Message Digests - * - * Compile and link with md5.c. If you don't have getopt() in your library - * also include getopt.c. For MSDOS you can also link with the wildcard - * initialization function (wildargs.obj for Turbo C and setargv.obj for MSC) - * so that you can use wildcards on the commandline. - * - * Written March 1993 by Branko Lankester - * Modified June 1993 by Colin Plumb for altered md5.c. - */ -#include -#include -#include "md5.h" - -#ifdef UNIX -#define FOPRTXT "r" -#define FOPRBIN "r" -#else -#ifdef VMS -#define FOPRTXT "r","ctx=stm" -#define FOPRBIN "rb","ctx=stm" -#else -#define FOPRTXT "r" -#define FOPRBIN "rb" -#endif -#endif - -extern char *optarg; -extern int optind; - -void usage(); -void print_digest(); -int mdfile(FILE *fp, unsigned char *digest); -int do_check(FILE *chkf); - -char *progname; -int verbose = 0; -int bin_mode = 0; - -void -main(int argc, char **argv) -{ - int opt, rc = 0; - int check = 0; - FILE *fp; - unsigned char digest[16]; - - progname = *argv; - while ((opt = getopt(argc, argv, "cbvp:h")) != EOF) { - switch (opt) { - case 'c': check = 1; break; - case 'v': verbose = 1; break; - case 'b': bin_mode = 1; break; - default: usage(); - } - } - argc -= optind; - argv += optind; - if (check) { - switch (argc) { - case 0: fp = stdin; break; - case 1: if ((fp = fopen(*argv, FOPRTXT)) == NULL) { - perror(*argv); - exit(2); - } - break; - default: usage(); - } - exit(do_check(fp)); - } - if (argc == 0) { - if (mdfile(stdin, digest)) { - fprintf(stderr, "%s: read error on stdin\n", progname); - exit(2); - } - print_digest(digest); - printf("\n"); - exit(0); - } - for ( ; argc > 0; --argc, ++argv) { - if (bin_mode) - fp = fopen(*argv, FOPRBIN); - else - fp = fopen(*argv, FOPRTXT); - if (fp == NULL) { - perror(*argv); - rc = 2; - continue; - } - if (mdfile(fp, digest)) { - fprintf(stderr, "%s: error reading %s\n", progname, *argv); - rc = 2; - } else { - print_digest(digest); - printf(" %c%s\n", bin_mode ? '*' : ' ', *argv); - } - fclose(fp); - } - exit(rc); -} - -void -usage() -{ - fprintf(stderr, "usage: md5sum [-bv] [-c [file]] | [file...]\n"); - fprintf(stderr, "Generates or checks MD5 Message Digests\n"); - fprintf(stderr, " -c check message digests (default is generate)\n"); - fprintf(stderr, " -v verbose, print file names when checking\n"); - fprintf(stderr, " -b read files in binary mode\n"); - fprintf(stderr, "The input for -c should be the list of message digests and file names\n"); - fprintf(stderr, "that is printed on stdout by this program when it generates digests.\n"); - exit(2); -} - -int -mdfile(FILE *fp, unsigned char *digest) -{ - unsigned char buf[1024]; - MD5_CTX ctx; - int n; - - MD5Init(&ctx); - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) - MD5Update(&ctx, buf, n); - MD5Final(digest, &ctx); - if (ferror(fp)) - return -1; - return 0; -} - -void -print_digest(unsigned char *p) -{ - int i; - - for (i = 0; i < 16; ++i) - printf("%02x", *p++); -} - -int -hex_digit(int c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - return -1; -} - -int -get_md5_line(FILE *fp, unsigned char *digest, char *file) -{ - char buf[1024]; - int i, d1, d2, rc; - char *p = buf; - - if (fgets(buf, sizeof(buf), fp) == NULL) - return -1; - - for (i = 0; i < 16; ++i) { - if ((d1 = hex_digit(*p++)) == -1) - return 0; - if ((d2 = hex_digit(*p++)) == -1) - return 0; - *digest++ = d1*16 + d2; - } - if (*p++ != ' ') - return 0; - /* - * next char is an attribute char, space means text file - * if it's a '*' the file should be checked in binary mode. - */ - if (*p == ' ') - rc = 1; - else if (*p == '*') - rc = 2; - else { - fprintf(stderr, "%s: unrecognized line: %s", progname, buf); - return 0; - } - ++p; - i = strlen(p); - if (i < 2 || i > 255) - return 0; - p[i-1] = '\0'; - strcpy(file, p); - return rc; -} - -int -do_check(FILE *chkf) -{ - int rc, ex = 0, failed = 0, checked = 0; - unsigned char chk_digest[16], file_digest[16]; - char filename[256]; - FILE *fp; - int flen = 14; - - while ((rc = get_md5_line(chkf, chk_digest, filename)) >= 0) { - if (rc == 0) /* not an md5 line */ - continue; - if (verbose) { - if (strlen(filename) > flen) - flen = strlen(filename); - fprintf(stderr, "%-*s ", flen, filename); - } - if (bin_mode || rc == 2) - fp = fopen(filename, FOPRBIN); - else - fp = fopen(filename, FOPRTXT); - if (fp == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, filename); - ex = 2; - continue; - } - if (mdfile(fp, file_digest)) { - fprintf(stderr, "%s: error reading %s\n", progname, filename); - ex = 2; - fclose(fp); - continue; - } - fclose(fp); - if (memcmp(chk_digest, file_digest, 16) != 0) { - if (verbose) - fprintf(stderr, "FAILED\n"); - else - fprintf(stderr, "%s: MD5 check failed for '%s'\n", progname, filename); - ++failed; - } else if (verbose) - fprintf(stderr, "OK\n"); - ++checked; - } - if (verbose && failed) - fprintf(stderr, "%s: %d of %d file(s) failed MD5 check\n", progname, failed, checked); - if (!checked) { - fprintf(stderr, "%s: no files checked\n", progname); - return 3; - } - if (!ex && failed) - ex = 1; - return ex; -} +/* + * md5sum.c - Generate/check MD5 Message Digests + * + * Compile and link with md5.c. If you don't have getopt() in your library + * also include getopt.c. For MSDOS you can also link with the wildcard + * initialization function (wildargs.obj for Turbo C and setargv.obj for MSC) + * so that you can use wildcards on the commandline. + * + * Make sure that you compile with -DHIGHFIRST if you are on a big-endian + * system. Here are some examples of correct MD5 sums: + * + * % echo "The meeting last week was swell." | md5sum + * 050f3905211cddf36107ffc361c23e3d + * + * % echo 'There is $1500 in the blue box.' | md5sum + * 05f8cfc03f4e58cbee731aa4a14b3f03 + * + * If you get anything else than this, then you've done something wrong. ;) + * + * Written March 1993 by Branko Lankester + * Modified June 1993 by Colin Plumb for altered md5.c. + */ +#include /* Added RKNOP 960111 */ +#include +#include +#include "md5.h" +#ifdef AMIGA /* Added RKNOP 960111 */ +#include "getopt.h" +#define getopt(a,b,c) pgp_getopt((a),(b),(c)) +#endif + +#ifdef UNIX +#define FOPRTXT "r" +#define FOPRBIN "r" +#else +#ifdef VMS +#define FOPRTXT "r","ctx=stm" +#define FOPRBIN "rb","ctx=stm" +#else +#define FOPRTXT "r" +#define FOPRBIN "rb" +#endif +#endif + +extern char *optarg; +extern int optind; + +void usage(); +void print_digest(); +int mdfile(FILE *fp, unsigned char *digest); +int do_check(FILE *chkf); + +char *progname; +int verbose = 0; +int bin_mode = 0; + +void +main(int argc, char **argv) +{ + int opt, rc = 0; + int check = 0; + FILE *fp; + unsigned char digest[16]; + + progname = *argv; + while ((opt = getopt(argc, argv, "cbvp:h")) != EOF) { + switch (opt) { + case 'c': check = 1; break; + case 'v': verbose = 1; break; + case 'b': bin_mode = 1; break; + default: usage(); + } + } + argc -= optind; + argv += optind; + if (check) { + switch (argc) { + case 0: fp = stdin; break; + case 1: if ((fp = fopen(*argv, FOPRTXT)) == NULL) { + perror(*argv); + exit(2); + } + break; + default: usage(); + } + exit(do_check(fp)); + } + if (argc == 0) { + if (mdfile(stdin, digest)) { + fprintf(stderr, "%s: read error on stdin\n", progname); + exit(2); + } + print_digest(digest); + printf("\n"); + exit(0); + } + for ( ; argc > 0; --argc, ++argv) { + if (bin_mode) + fp = fopen(*argv, FOPRBIN); + else + fp = fopen(*argv, FOPRTXT); + if (fp == NULL) { + perror(*argv); + rc = 2; + continue; + } + if (mdfile(fp, digest)) { + fprintf(stderr, "%s: error reading %s\n", progname, *argv); + rc = 2; + } else { + print_digest(digest); + printf(" %c%s\n", bin_mode ? '*' : ' ', *argv); + } + fclose(fp); + } + exit(rc); +} + +void +usage() +{ + fprintf(stderr, "usage: md5sum [-bv] [-c [file]] | [file...]\n"); + fprintf(stderr, "Generates or checks MD5 Message Digests\n"); + fprintf(stderr, " -c check message digests (default is generate)\n"); + fprintf(stderr, " -v verbose, print file names when checking\n"); + fprintf(stderr, " -b read files in binary mode\n"); + fprintf(stderr, "The input for -c should be the list of message digests and file names\n"); + fprintf(stderr, "that is printed on stdout by this program when it generates digests.\n"); + exit(2); +} + +int +mdfile(FILE *fp, unsigned char *digest) +{ + unsigned char buf[1024]; + MD5_CTX ctx; + int n; + + MD5Init(&ctx); + while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) + MD5Update(&ctx, buf, n); + MD5Final(digest, &ctx); + if (ferror(fp)) + return -1; + return 0; +} + +void +print_digest(unsigned char *p) +{ + int i; + + for (i = 0; i < 16; ++i) + printf("%02x", *p++); +} + +int +hex_digit(int c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return -1; +} + +int +get_md5_line(FILE *fp, unsigned char *digest, char *file) +{ + char buf[1024]; + int i, d1, d2, rc; + char *p = buf; + + if (fgets(buf, sizeof(buf), fp) == NULL) + return -1; + + for (i = 0; i < 16; ++i) { + if ((d1 = hex_digit(*p++)) == -1) + return 0; + if ((d2 = hex_digit(*p++)) == -1) + return 0; + *digest++ = d1*16 + d2; + } + if (*p++ != ' ') + return 0; + /* + * next char is an attribute char, space means text file + * if it's a '*' the file should be checked in binary mode. + */ + if (*p == ' ') + rc = 1; + else if (*p == '*') + rc = 2; + else { + fprintf(stderr, "%s: unrecognized line: %s", progname, buf); + return 0; + } + ++p; + i = strlen(p); + if (i < 2 || i > 255) + return 0; + p[i-1] = '\0'; + strcpy(file, p); + return rc; +} + +int +do_check(FILE *chkf) +{ + int rc, ex = 0, failed = 0, checked = 0; + unsigned char chk_digest[16], file_digest[16]; + char filename[256]; + FILE *fp; + int flen = 14; + + while ((rc = get_md5_line(chkf, chk_digest, filename)) >= 0) { + if (rc == 0) /* not an md5 line */ + continue; + if (verbose) { + if (strlen(filename) > flen) + flen = strlen(filename); + fprintf(stderr, "%-*s ", flen, filename); + } + if (bin_mode || rc == 2) + fp = fopen(filename, FOPRBIN); + else + fp = fopen(filename, FOPRTXT); + if (fp == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, filename); + ex = 2; + continue; + } + if (mdfile(fp, file_digest)) { + fprintf(stderr, "%s: error reading %s\n", progname, filename); + ex = 2; + fclose(fp); + continue; + } + fclose(fp); + if (memcmp(chk_digest, file_digest, 16) != 0) { + if (verbose) + fprintf(stderr, "FAILED\n"); + else + fprintf(stderr, "%s: MD5 check failed for '%s'\n", progname, filename); + ++failed; + } else if (verbose) + fprintf(stderr, "OK\n"); + ++checked; + } + if (verbose && failed) + fprintf(stderr, "%s: %d of %d file(s) failed MD5 check\n", progname, failed, checked); + if (!checked) { + fprintf(stderr, "%s: no files checked\n", progname); + return 3; + } + if (!ex && failed) + ex = 1; + return ex; +}