int main(int argc, char** argv)
{
	int i, usealt;
	const char * pin, * label;
#ifdef CTAPI
	void* mutex;
#endif

	/* Check args */
	if (argc < 4) {
		fprintf(stderr, "Usage: [-a] pin label path...\n");
		fprintf(stderr, "Signs the specified file(s) and/or files within the specified directory(ies).\n");
		fprintf(stderr, "  -a  use :p7s instead of .p7s extension (alternate data stream on Windows)\n");
		return 1;
	}
	usealt  = strcmp(argv[1], "-a") == 0;
	pin     = !usealt ? argv[1] : argv[2];
	label   = !usealt ? argv[2] : argv[3];
	sig_ext = !usealt ? ".p7s"  : ":p7s";

	/* Disable buffering on stdout/stderr to prevent mixing the order of
	   messages to stdout/stderr when redirected to the same log file */
	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stderr, NULL, _IONBF, 0);

	/* Log the args */
	log_inf("pin=****; label='%s'", label);

#ifdef CTAPI
	/* Create a mutex/sem/lock for controlling access to token.
	   CTAPI implementations must NOT allow simultaneous access to token. */
	mutex = create_lock(MUTEX_KEY);
	if ((int)mutex < 0) {
		log_wrn(
			"couldn't create mutex; another inst. of '%s' is likely running", argv[0]);
		return -1;
	}
#endif

	/* For each path arg, sign either the specified file
	   or all the files in the specified directory */
	for (i = !usealt ? 3 : 4; i < argc; i++) {
		int err;
		struct stat info;
		char* path = argv[i];

		/* Trim trailing slashes from path (required for Windows stat) */
		int j = strlen(path);
		while (--j >= 0 && (path[j] == '/' || path[j] == '\\'))
			path[j] = 0;

		/* Log the path */
		log_inf("path='%s'", path);

		/* Verify the specified path exists */
		err = stat(path, &info);
		if (err) {
			int e = errno;
			log_err("error accessing path '%s': %s", path, strerror(e));
			continue;
		}

		if (S_ISDIR(info.st_mode)) /* DIRECTORY */
			sign_files(path, pin, label); /* Sign all files in the specified directory */
		else /* FILE */
			sign_file(path, pin, label);  /* Sign the specified file */
	}

	/* Clean up */
	release_template();

#ifdef CTAPI
	/* Release mutex/sem/lock here. */
	release_lock(mutex);
#endif

#if defined(_WIN32) && defined(DEBUG)
	_CrtDumpMemoryLeaks();
#endif
	return 0;
}
int main(int argc, char **argv)
{
	int i;
	FILE* fp;
	unsigned char buf[0x10000], hash[32]; /* 32 => 256-bit sha256 */
	sha256_context ctx;
	char name[256];
	const unsigned char *pCms = 0;
	int count = argc >= 4 ? atoi(argv[3]) : 1;
	int wait  = argc >= 5 ? atoi(argv[4]) : 10000;

#if defined(_WIN32) && defined(_DEBUG)
	atexit((void(*)(void))_CrtDumpMemoryLeaks);
#endif

	/* Check args */
	if (argc < 3) {
		printf("Usage: pin label [count [wait-in-milliseconds]]\nSign this executable (%s).\n", argv[0]);
		return 1;
	}

	/* Create a SHA-256 hash of this executable */
	sha256_starts(&ctx);
	fp = fopen(argv[0], "rb");
	if (!fp) {
		int e = errno;
		printf("error opening file '%s': %s\n", argv[0], strerror(e));
		return e;
	}
	for (;;) {
		int n = fread(buf, 1, sizeof(buf), fp);
		if (n <= 0)
			break;
		sha256_update(&ctx, buf, n);
	}
	fclose(fp);
	sha256_finish(&ctx, hash);

	/* Sign the hash of this executable n times, where n = count */
	for (i = 0; i < count; i++) {
		int len;
		long start, end;
		if (i > 0 && count > 1) {
			printf("wait %d milliseconds for next signature\n", wait);
			usleep(wait * 1000);
		}
		start = GetTickCount();
		len   = sign_hash(argv[1], argv[2], hash, sizeof(hash), &pCms);
		end   = GetTickCount();
		printf("sign_hash returned: %d, time used: %ld ms\n", len, end - start);
		if (len <= 0) /* sign_hash error */
			break;
		sprintf(name, "%s.p7s", argv[0]);
		fp = fopen(name, "wb");\
		if (!fp) {
			int e = errno;
			printf("error opening file '%s': %s\n", name, strerror(e));
			break;
		}
		fwrite(pCms, 1, len, fp);
		fclose(fp);
	}
	release_template();

	return 0;
}