/*
 *	dmsgdig - メッセージダイジェスト計算ツール
 *	Copyright (C) 2009 Naoyuki Sawa
 *
 *	* Sat Jan 10 20:05:27 JST 2009 Naoyuki Sawa
 *	- 1st リリース。
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#define DIE() abort()
#define __CLIP_H__
#include "../../clipcode.h"
#include "../../clipcode.c"

#define VERSION "20090110"

/////////////////////////////////////////////////////////////////////////////

int
main(int argc, char* argv[])
{
	int retval;
	int i;
	int j;
	FILE* fp;
	int len;
	unsigned char digest[20];
	//
	int digest_len = 16; /* 16 = MD5, 20 = SHA-1 */
	int with_filename = 1;
	//
	unsigned char* buf = NULL;
	int buflen = 0;

	if(argc == 1) {
		printf("dmsgdig - メッセージダイジェスト計算ツール (%s) Naoyuki Sawa\n", VERSION);
		printf("\n");
		printf("使い方: dmsgdig [[オプション] ファイル名 [[オプション] ファイル名 [...]]]\n");
		printf("\n");
		printf("アルゴリズム選択オプション:\n");
		printf("   -m   MD5アルゴリズムを使用します。    (初期設定)\n");
		printf("   -s   SHA-1アルゴリズムを使用します。\n");
		printf("ファイル名出力オプション:\n");
		printf("   -H   ファイル名を出力します。         (初期設定)\n");
		printf("   -h   ファイル名を出力しません。\n");
		printf("\n");
		printf("ファイル名の指定には、ワイルドカードも利用できます。\n");
		exit(1);
	}

	for(i = 1; i < argc; i++) {
		if(argv[i][0] == '-') {
			switch(argv[i][1]) {
			case 'm':
				digest_len = 16;
				break;
			case 's':
				digest_len = 20;
				break;
			case 'h':
				with_filename = 0;
				break;
			case 'H':
				with_filename = 1;
				break;
			default:
				fprintf(stderr, "### %s: オプションが不正です。\n", argv[i]);
				exit(1);
			}
			continue;
		}

		/* ファイルを開きます。 */
		fp = fopen(argv[i], "rb");
		if(!fp) {
			fprintf(stderr, "### %s: fopen が失敗しました。\n", argv[i]);
			exit(1);
		}

		/* ファイルサイズを取得します。 */
		retval = fseek(fp, 0, SEEK_END);
		if(retval) {
			fprintf(stderr, "### %s: fseek が失敗しました。\n", argv[i]);
			exit(1);
		}
		len = ftell(fp);
		if(len < 0) {
			fprintf(stderr, "### %s: ftell が失敗しました。\n", argv[i]);
			exit(1);
		}
		rewind(fp);

		/* 必要に応じて、バッファを拡張します。 */
		if(len > buflen) {
			buflen = len;
			buf = realloc(buf, buflen);
			if(!buf) {
				fprintf(stderr, "### %s: realloc が失敗しました。\n", argv[i]);
				exit(1);
			}
		}

		/* ファイルを読み込み、閉じます。 */
		retval = fread(buf, 1, len, fp);
		if(retval != len) {
			fprintf(stderr, "### %s: fread が失敗しました。\n", argv[i]);
			exit(1);
		}
		fclose(fp);

		/* メッセージダイジェストを計算し、出力します。 */
		switch(digest_len) {
		case 16:
			md5_digest(digest, buf, len);
			break;
		case 20:
			sha1_digest(digest, buf, len);
			break;
		default:
			abort(); /* 有り得ない */
		}
		for(j = 0; j < digest_len; j++) {
			printf("%02x", digest[j]);
		}
		if(with_filename) {
			printf(" %s", argv[i]);
		}
		printf("\n");
	}

	return 0;
}
