# $Compile(*): %b %o -mMkcmd %f && %b %o prog.c
# $Mkcmd(*): ${mkcmd-mkcmd} %f

from '<sys/types.h>'
from '<time.h>'
from '<unistd.h>'
from '<stdlib.h>'
from '"machine.h"'
from '"passgen.h"'
from '"main.h"'

require "std_help.m" "std_version.m"

%i
static char rcsid[] =
	"$Id: passgen.m,v 2.4 2008/07/10 17:58:29 ksb Exp $";
%%

basename "passgen" ""

boolean 'd' {
	named "bDebug"
	help "enable debugging checks"
	hidden
}
boolean 't' {
	named "bTerse"
	help "just give the password, not the explanation"
	static
}

# Foo, blech, yucko.  mkcmd can't intialize a variable to a function
# value without doing the type conversion (even if it doesn't need it).
before {
	named "InitSeed"
	update "%n(&dSeed);"
}
double 'S' {
	named "dSeed"
	help "specify a seed to the random number generator"
	parameter "seed"
	user "set_seed((long)%n);"
	local
	verify
	once
	hidden
}

%h
/* This is for the string that gets encrypted by DES for the random number
 * generator.  (8 should be all that is needed, but 15 doesn't hurt)
 */
#define MAX_STRING_LEN 15
%%
excludes "si"
string[15] 's' {
	named "pcRandString"
	init '"BlecherousHack"'
	help "give a string to encrypt for random number generation"
	verify
	once
}

boolean 'i' {
	named "bInteractive"
	help "prompt for an input string for random number generation"
}

integer 'p' {
	named "iPunctuate"
	help "percentage of words to contain punctuation symbols"
	init "20"
	parameter "percent"
	user ' if (%n<0 || %n>100) { fprintf(stderr, "%%s: punctuation percentage (%%d) outside the range of 0-100\\n", progname, %n); exit (1); }'
	once
	verify
}

integer 'c' {
	named "iCapitalize"
	help "percentage of syllables to capitalize"
	parameter "percent"
	init "30"
	user 'if (%n<0||%n>100){fprintf(stderr, "%%s: capitalization percentage (%%d) outside the range of 0-100\\n", progname, %n); exit (1); }'
	once
	verify
}

integer 'm' {
	named "iMin"
	help "minimum size of generated password"
	parameter "min"
	init "6"
	user 'if (%n<1){fprintf(stderr, "%%s: minimum size (%%d) is less than 1.\\n", progname, %n); exit (1); }'
	local
	verify
	once
}

integer 'M' {
	named "iMax"
	help "maximum size of generated password"
	init "8"
	parameter "max"
	local
	verify
	once
}

integer 'n' {
	named "iCount"
	help "number of passwords to generate"
	user 'if (%n<1){fprintf(stderr, "%%s: count (%%d) less than 1.\\n", progname, %n); exit (1); }'
	init "1"
	parameter "count"
	local
	verify
	once
}

# delete the bogus update when word checking is implimented
# we might wish to make this default as well. (change init and help)
boolean 'w' {
	named "bWordchk"
	help "check generated passwords for being a good password"
	user 'fprintf(stderr, "%%s: Warning: word checking currently not implimented.\\n", progname);'
	init "0"
	update "%n=0;"
	static
}

boolean 'r' {
	named "bLetters"
	help "make passwords out of random characters (rather than syllables)"
}

exit {
	named "Invoker"
	update "%n(%rnn, %rmn, %rMn);"
}

%c

/* Initialize the random number generator with a pseudorandom seed
 */
static void
InitSeed(pdSeed)
double *pdSeed;		/* pointer to Seed memory location */
{
	*pdSeed=time(0)*getpid();
}


/*
 *   Error check the min and max lengths of the generated password
 */
int
Lengthcheck(iMin, iMax)
int iMin;		/* Minimum length a password should be */
int iMax;		/* Maximum length a password can be */
{
	if (iMin > iMax) {
		fprintf(stderr, "%s:  min length (%d) > max passwd length (%d)\n", progname, iMin, iMax);
		exit (1);
	}
	return 0;
}


/* The invocation of the real program
 */
static void
Invoker(iCount, iMin, iMax)
int iCount;		/* Number of passwds to generate */
int iMin;		/* Minimum length a password should be */
int iMax;		/* Maximum length a password can be */
{
	register char  *pchUnhyphen;
	register char  *pchHyphen;
	int i;

	/* error checking */
	Lengthcheck(iMin, iMax);

	pchUnhyphen= calloc(sizeof(char), iMax+1);
	pchHyphen= calloc(sizeof(char), 2*iMax);

	for (i=1; i<=iCount; ++i) {
		if (bLetters) {
			/* build a password of random characters */
			(void) randomchars(pchUnhyphen, iMin, iMax, bWordchk);
			(void) fprintf(stdout, "%s\n", pchUnhyphen);
		} else {
			/* build a password of random syllables */
			(void) randomword(pchUnhyphen, pchHyphen, iMin, iMax, bWordchk);
			if (bTerse) {
				(void) fprintf(stdout, "%s\n", pchUnhyphen);
			} else {
				(void) fprintf(stdout, "%s (%s)\n", pchUnhyphen, pchHyphen);
			}
		}
		(void) fflush(stdout);
	}
	free(pchUnhyphen);
	free(pchHyphen);
	exit(0);
}
%%
