/*
    crypt.c

    Vigenere and Substitution Cipher Encrypter
    Copyright (C) 1997,1998 Robert Muth <muth@cs.arizona.edu>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; version 2 of June 1991.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program in form of the file COPYING; 
    if not, write to the 

    Free Software Foundation, Inc. <http://www.fsf.org>
    59 Temple Place, Suite 330, 
    Boston, MA 02111-1307  USA
*/


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>

int DEBUG = 1;


int char2num(int c)
{
    if( isalpha(c) )
        return tolower(c) - 'a' + 1;
    else
        return 0;
}

int num2char(int c)
{
    if( c == 0)
        return ' ';
    else
        return c - 1 + 'a';
}

/*========================================================
Substitution cipher with random permutation
========================================================*/
void Substitute(char *optarg)
{
    int c;

    int translate[27];

    srand( atoi(optarg) );
    
    for( c=0; c < 27; c++ )
    {
        translate[c] = c;
    }

    for( c=0; c < 26; c++ )
    {
        int temp;
        int index;

        index = c + rand() % (27 - c);
        temp = translate[c];
        translate[c] = translate[index];
        translate[index] = temp;
    }

    if( DEBUG )
    {
        int inverse[32];
        
        fprintf(stderr,"Substitution Table:\n");
        
        for( c=0; c < 27; c++ )
        {
            fprintf(stderr,"%2d ",translate[c]);
        }
        fprintf(stderr,"\n");

        for( c=0; c < 27; c++ )
        {
            inverse[ translate[c] ] = c;
        }
            
        fprintf(stderr,"Inverse:\n");
        
        for( c=0; c < 27; c++ )
        {
            fprintf(stderr,"%2d ",inverse[c]);
        }
        fprintf(stderr,"\n");
    }
    

    
    while( EOF != (c=getchar()) )
    {
        if( c == '\n' )
        {
            putchar(c);
        }
        else
        {
            putchar( num2char( translate[char2num(c)]) );
        }
    }
}

/*========================================================
Vigenere encryption with given key
========================================================*/
void Vigenere( char *optarg)
{
    int i,c,len;

    for( len=0; optarg[len] != 0; len++ )
    {
        optarg[len] = char2num( optarg[len] );
    }

    if( DEBUG )
    {
        fprintf(stderr,"Vigenere Key:\n");
        
        for( c=0; c < len; c++ )
        {
            fprintf(stderr,"%c", num2char(optarg[c]));
        }
        fprintf(stderr,"\n");

        fprintf(stderr,"Inverse:\n");
        
        for( c=0; c < len; c++ )
        {
            fprintf(stderr,"%c",num2char((27-optarg[c])%27));
        }
        fprintf(stderr,"\n");
    }
    

    i=0;
    while( EOF != (c=getchar()) )
    {
        if( c == '\n' )
        {
            putchar(c);
        }
        else
        {
            putchar( num2char( (char2num(c) + optarg[i]) % 27 ) );
            i++;
            if( i == len )
                i =0;
        }

    }
}

/*========================================================
No encryption just conversion to lower case letters
========================================================*/
void Filter()
{
    int c;
    
    while( EOF != (c=getchar()) )
    {
        if( isalpha(c) )
        {
            putchar( tolower(c) );
        }
        else if( c == '\n' )
        {
            putchar(c);
        }
        else
        {
            putchar( ' ');
        }
    }
}


/*========================================================
Usage  
========================================================*/

int Usage()
{
    printf("usage\n"
           "\tcrypt [method] - enrypt stdin with one of several methods\n"
           "methods\n"
           "\t-v\tVigenere key - vigenere encryption with given key \n"
           "\t-s\tsubstitution random seed - encryption with random substitution\n"
           "\t-f\tfilter - no encryption just filtering to lowercase letters\n"
           "\t-h\thelp\n");
           
    return -1;
}

/*========================================================
Main  
========================================================*/

int main(int argc, char *argv[])
{
    int i;

    while( EOF != (i = getopt(argc,argv,"hfs:v:")) )
    {
        switch(i)
        {
        case '?':
        case 'h':
            return Usage();
            break;
        case 'f':
            Filter();
            break;
        case 's':
            Substitute(optarg);
            break;
        case 'v':
            Vigenere(optarg);
            break;
        default:
            break;
        }
    }
    return 0;
}
/* eof */

