#!/usr/bin/perl
################################################################
# rotdecr.pl : Rotor cipher over the alphabet [A..Z]           #
#   Decryption                                                 #
#--------------------------------------------------------------#
# Rotor wiring and number of rotors is read from the file      #
#   rotors.txt in the same directory.                          #
#   Each line defines a rotor.                                 #
#   The line is transformed to an alphabet by &makeperm        #
#   and stored int the list @alphlist.                         #
# Command line parameter: an integer that defines the initial  #
#   states of the rotors by the digits of its representation   #
#   in base 26.                                                #
# Input from STDIN : ciphertext                                #
# Output to STDOUT : plaintext                                 #
#--------------------------------------------------------------#
# Klaus Pommerening 2013-November-22                           #
#                                                              #
# This program is freeware. Use it as you like.                #
# Usual disclaimers apply.                                     #
################################################################

require "auxcrypt.pl";     # Use standard alphabet
                           #   as global variables $alphabet,
                           #   @alphabet, and %sa.
                           # Use procedures
                           #   &gettext, &makeperm, &puttext.
$pos = $ARGV[0];                 # Number that defines the state
$nofrot = 0;                     # Number of rotors
@alphlist = ("Nullposition");    # Dummy alphabet
                                 #   for nonexisting rotor 0
open(IN,"rotors.txt");                # Read keys for rotor wiring.
while ($line = <IN>){
    $nofrot++;                        # Count them,
    push @alphlist, &makeperm($line); # transform and keep them.
    }
close(IN);

@invlist = ("Nullposition");          # Invert rotor alphabets
for ($i = 1; $i <= $nofrot; $i++) {   # For each rotor
  push @invlist, &invertsubst($alphlist[$i]); # keep inverse substitution.
print "Inverse alphabet no ", $i, ": ", $invlist[$i], "\n";
  }
$ciphertext = &gettext;               # Get ciphertext from standard
                                      #   input,
@cipherlist = split(//,$ciphertext);  # split as list of characters.
$plaintext = "";

@poslist = (0);                       # Determine initial positions
for ($i = 1; $i <= $nofrot; $i++) {
    $p = int($pos / 26**($nofrot - $i)); # by decomposing the argument
    $q = $p % 26;                        # into its base 26 digits.
    push @poslist, $q;
    }

foreach $char (@cipherlist) {            # Take ciphertext letter.
     #---------------------------------------------------------#
     # Then first step rotors according to odometer logic.     #
     #   This part of the program may be replaced by any other #
     #   control logic.                                        #
     #---------------------------------------------------------#
  $pos++;                                # increment position indicator,
  @poslist = (0);
  for ($i = 1; $i <= $nofrot; $i++) {    # and update rotor states
    $p = int($pos / 26**($nofrot - $i)); # following odometer logic
    $q = $p % 26;
    push @poslist, $q;
    } #--- End of rotor movement ------------------------------#
  for ($i = $nofrot; $i >= 1; $i--) {    # Apply rotor substitutions
                                         # in reverse order
                                         # and with inverse permutations.
    $char = &rotor($invlist[$i], $poslist[$i], $char); # Feed rotor.
    }
  $plaintext .= $char;                  # Append result to ciphertext
  }
&puttext($plaintext);                   # Write ciphertext
