/*1* Copyright (c) 1989, 19932* The Regents of the University of California. All rights reserved.3*4* This code is derived from software contributed to Berkeley by5* Rick Adams.6*7* Authors:8* Stan King, John Eldridge, based on algorithm suggested by9* Bob Morris10* 29-Sep-8211*12* Redistribution and use in source and binary forms, with or without13* modification, are permitted provided that the following conditions14* are met:15* 1. Redistributions of source code must retain the above copyright16* notice, this list of conditions and the following disclaimer.17* 2. Redistributions in binary form must reproduce the above copyright18* notice, this list of conditions and the following disclaimer in the19* documentation and/or other materials provided with the distribution.20* 3. Neither the name of the University nor the names of its contributors21* may be used to endorse or promote products derived from this software22* without specific prior written permission.23*24* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND25* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE26* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE27* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE28* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL29* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS30* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)31* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT32* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY33* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF34* SUCH DAMAGE.35*/3637#include <errno.h>38#include <math.h>39#include <stdio.h>40#include <stdlib.h>41#include <string.h>42#include <ctype.h>43#include <unistd.h>4445#define LINELENGTH 204846#define ROTATE(ch, perm) \47isascii(ch) ? ( \48isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \49islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch) : ch5051/*52* letter frequencies (taken from some unix(tm) documentation)53* (unix is a trademark of Bell Laboratories)54*/55static double stdf[26] = {567.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04,570.42, 3.81, 2.69, 5.92, 6.96, 2.91, 0.08, 6.63, 8.77, 9.68,582.62, 0.81, 1.88, 0.23, 2.07, 0.06,59};6061static void printit(char *);6263int64main(int argc, char **argv)65{66int ch, dot, i, nread, winnerdot = 0;67char *inbuf;68int obs[26], try, winner;6970if (argc > 1)71printit(argv[1]);7273if (!(inbuf = malloc((size_t)LINELENGTH))) {74(void)fprintf(stderr, "caesar: out of memory.\n");75exit(1);76}7778/* adjust frequency table to weight low probs REAL low */79for (i = 0; i < 26; ++i)80stdf[i] = log(stdf[i]) + log(26.0 / 100.0);8182/* zero out observation table */83bzero(obs, 26 * sizeof(int));8485if ((nread = read(STDIN_FILENO, inbuf, (size_t)LINELENGTH)) < 0) {86(void)fprintf(stderr, "caesar: %s\n", strerror(errno));87exit(1);88}89for (i = nread; i--;) {90ch = (unsigned char) inbuf[i];91if (isascii(ch)) {92if (islower(ch))93++obs[ch - 'a'];94else if (isupper(ch))95++obs[ch - 'A'];96}97}9899/*100* now "dot" the freqs with the observed letter freqs101* and keep track of best fit102*/103for (try = winner = 0; try < 26; ++try) { /* += 13) { */104dot = 0;105for (i = 0; i < 26; i++)106dot += obs[i] * stdf[(i + try) % 26];107/* initialize winning score */108if (try == 0)109winnerdot = dot;110if (dot > winnerdot) {111/* got a new winner! */112winner = try;113winnerdot = dot;114}115}116117for (;;) {118for (i = 0; i < nread; ++i) {119ch = (unsigned char) inbuf[i];120putchar(ROTATE(ch, winner));121}122if (nread < LINELENGTH)123break;124if ((nread = read(STDIN_FILENO, inbuf, (size_t)LINELENGTH)) < 0) {125(void)fprintf(stderr, "caesar: %s\n", strerror(errno));126exit(1);127}128}129exit(0);130}131132static void133printit(char *arg)134{135int ch, rot;136137if ((rot = atoi(arg)) < 0) {138(void)fprintf(stderr, "caesar: bad rotation value.\n");139exit(1);140}141while ((ch = getchar()) != EOF)142putchar(ROTATE(ch, rot));143exit(0);144}145146147