/*
* modified from authtest.c by vesely in milan on 8 aug 2006
* authtest.c: Copyright 1998 - 2004 Double Precision, Inc.
*
* check if a given user exists
*
* BUG: aliases.dat is not considered
*
*/

static char const usage[] =
"usage:\n"
"\ttestmailuser -h\n"
"\ttestmailuser [-v] [-R count] user@domain...\n"
"The first format is only useful to print this note.\n"
"The second format calls Courier's authlib to verify the address given.\n"
"If verbose, the resulting address is printed.\n"
"The -R option forces a minimal number of successful calls to be executed\n"
"and prints the time taken for doing that\n"
"\n"
"Exit code is 0 if all calls were successful and no error occurred\n"
"BUG: aliases.dat is not considered, so don't give aliases to test!\n";

#include	<auth.h>
//#include	<authstaticlist.h>
//#include	<courierauthsasl.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include <limits.h>
#include <inttypes.h>
#include	<errno.h>


static int verbose = 0;

static int callback(struct authinfo *a, void *dummy)
{
	(void)dummy;
	if (verbose && a && a->address)
		printf("%s\n", a->address);
	return (0);
}

int main(int argc, char *argv[])
{
	int i, rtc = 0, repeat = 0, user = 0;

	for (i = 1; i < argc; ++i)
	{
		char *a = argv[i];

		if (*a == '-')
		{
			int ch;
			
			for (ch = *++a; ch; ch = *++a)
			{
				switch (ch)
				{
					case 'R':
					{
						char *t = NULL;
						unsigned long l = i + 1 < argc? strtoul(argv[++i], &t, 0): 0;
						if (l <= 0 || l >= INT_MAX || t == NULL || *t != 0)
							fprintf(stderr,
								"testmailuser: invalid count %s\n",
								argv[i]);
							// thru
						else
						{
							repeat = (int)l;
							break;
						}
					}
					case 'h':
						puts(usage);
						return 1;
					case 'v':
						++verbose;
						break;
					default:
						if (verbose)
							fprintf(stderr,
								"testmailuser: discarding unknown option %s\n",
								argv[i]);
						break;
				}
			}
		}
		else
		{
			if (user <= 0)
				user = i;			
			break;
		}
	}
	
	if (user > 0)
	{
		struct timeval before, after;
		int count = 0;
		
		if (repeat > 0 && gettimeofday(&before, NULL))
		{
			fprintf(stderr,
				"testmailuser: cannot gettimeofday: %s\n",
				strerror(errno));
			return 2;
		}
		
		for (i = user; i < argc;)
		{
			if (auth_getuserinfo("courier", argv[i], callback, NULL))
			{
				rtc = 1;
				break;
			}
			
			++i;
			if (++count < repeat && i >= argc)
				i = user;
		}
		
		if (repeat > 0)
		{
			uint64_t tdiff;
			if (gettimeofday(&after, NULL))
			{
				fprintf(stderr,
					"testmailuser: cannot gettimeofday: %s\n",
					strerror(errno));
				return 2;
			}
			
			tdiff = (after.tv_sec - before.tv_sec) * 1000000LL +
				after.tv_usec - before.tv_usec;
			
			printf("%d successful call(s)%s in %" PRId64 " usec(s)\n",
				count, rtc? ", 1 unsuccessful": "", tdiff);
			if (rtc == 0 && count > 0)
				printf("avg: %" PRId64 " usec(s) per successful call\n",
					tdiff / count);
		}
	}

	return rtc;
}
