/****************************************************************
*								*
*		ENCRYPT/DECRYPT text file			*
*								*
* Uses the C encrypt function to encode a text file. The file	*
* may be decrypted using the companion DECRYPT program or read	*
* with the aid of the C decrypt function (if you know the key!)	*
*								*
* Program call syntax is:					*
*								*
*	$ ENCRYPT[/KEY=] infile outfile				*
*   or	$ DECRYPT[/KEY=] infile outfile				*
*								*
* Any items not given will be prompted for.			*
*								*
* The encrypt and decrypt functions work on blocks of 8 bytes	*
* at a time. The encrypted file is a 512-byte-block "binary"	*
* file, of which the first two bytes are a key check value,	*
* consisting of the first two bytes of the encryption of the	*
* key itself (giving it all would make it possible to find out	*
* the key from the file). The remainder is 9-byte records, in	*
* each of which, bytes 1-8 are the encrypted data, and byte 9	*
* is the number of encrypted bytes, which will always be 8,	*
* except for the last record, which may be shorter.		*
*								*
* V1.0 January 1986, Chris Doran, Sira Ltd.,			*
*	South Hill, Chislehurst, Kent, BR7 5EH, England.	*
*	Tel: +44 1 467 2636, Telex: 896649, Fax: +44 1 467 6515	*
*								*
* Modifications Record:						*
* =====================						*
*								*
****************************************************************/

#include <std.h>

TEXT *_pname {"e"};		/* Change to "d" for VAX DECRYPT */

int main(argc,argv)
int argc;
char **argv;
{
register FILE infile,outfile;
register int i,n;
register char *p;
static TINY ks[16][8],data[40];
static TINY key[8] = {' ',' ',' ',' ',' ',' ',' ',' '};
static BOOL have_key = NO;
static BOOL decrypting;

	/* Whether to encrypt or decrypt infile is determined by _pname.
	   On some systems (e.g. RSX), _main sets this according to the
	   name by which the task is installed/invoked. On others (e.g.
	   RT-11 and VMS) the compiled value above is used, and one must
	   have two separate programs, differing only in the _pname compile
	   time value. This inconsistency has been SPR'd to Whitesmiths'.

	  In any case, make sure it's spelt in full, in upper case, for
	  error messages, and set "decrypting" flag.
       */

	_pname = (decrypting = (*_pname == 'd')) ? &"DECRYPT" : &"ENCRYPT";

	infile = outfile = 0;

	for (n = 1; (p=argv[n]) != NULL; n++) {
		if ((i=scnstr(p,'/')) != lenstr(p)) {
			p += i+1;
			if (*p != 'k') errexit("IVQUAL, Unrecognised qualifier",p);
			if (i != 0) {	/* Non-null prefix is a filename */
				n--;
				*(p-1) = '\0';
			}
			while (*p != '\0' && *p != '=' && *p != ':') p++;
			if (*p != '\0') p++;
			/* Copy key, ignoring single quote ("), double ("") -> single */
			for (i = 0; *p != '\0' && i < 8; )
				if (*p != '"' || *p++ == *p) key[i++] = *p++;
			if (i <= 0) errexit("NULKEY,","Missing key specification");
			have_key = YES;
		}
		else if (!infile) infile = n;
		else if (!outfile) outfile = n;
	}

	argv[0] = &data;

	if (!infile) {
		do
			putstr(STDERR,"\n_From: ",NULL);
		while ((n=getlin(data,40)) == 1);
		if(n==0) return(YES);			/* ctrl/Z typed to cancel ENCRYPT */
		data[n-1] = '\0';			/* Remove trailing LF */
	}
	n = infile;
	if ((infile = open(argv[n],READ,decrypting)) < 0)
		errexit("OPNERR, Can't read",argv[n]);

	if (!have_key) {
		do
			putstr(STDERR,"\n_Key: ",NULL);
		while ((n=getlin(key,8)) == 1);
		if(n==0) return(YES);			/* Ctrl/Z typed to cancel ENCRYPT */
		if(key[n-1]=='\n') key[n-1] = ' ';	/* Remove trailing LF */
	}	

	if (!outfile) {
		do
			putstr(STDERR,"\n_To: ",NULL);
		while ((n=getlin(data,40)) == 1);
		if(n==0) return(YES);			/* ctrl/Z typed to cancel ENCRYPT */
		data[n-1] = '\0';			/* Remove trailing LF */
	}

	close(STDIN); close(STDOUT);			/* Free LUNs */
	n = outfile;
	if ((outfile = create(argv[n],WRITE,!decrypting)) < 0)
		errexit("OPNERR, Can't write",argv[n]);

/* Only allow upper-case letters in key, because of command line restrictions. */
	for (n = 0; n < 8; n++) key[n] = toupper(key[n]);

	bldks(ks,key);
	encrypt(key,ks);

	if (!decrypting) {					/* ENCRYPT */
		fwrite(outfile,key,2);
		while ((data[8]=fread(infile,data,8)) > 0)
			fwrite(outfile,encrypt(data,ks),9);
		data[8] = 0; fwrite(outfile,data,9);	/* Null terminator */	
	}
	else {							/* DECRYPT */
		fread(infile,data,2);
		if (key[0] != data[0] || key[1] != data[1])
			errexit("WRNGKEY,","Wrong key");
		while (fread(infile,data,9) > 0 && data[8] != 0)
			fwrite(outfile,decrypt(data,ks),data[8]);
	}

	return(YES);
}

/* Print error message, in VMS format, and exit with error. */

VOID errexit(s1,s2)
TEXT *s1,*s2;
{
	errfmt("\n%%%p-F-%p %p\n",_pname,s1,s2);
	exit(NO);
}
