139003Sbostic /* 239004Sbostic * Copyright (c) 1989 The Regents of the University of California. 339004Sbostic * All rights reserved. 439003Sbostic * 539004Sbostic * This code is derived from software contributed to Berkeley by 639004Sbostic * Rick Adams. 739003Sbostic * 839004Sbostic * Authors: 939004Sbostic * Stan King, John Eldridge, based on algorithm suggested by 1039004Sbostic * Bob Morris 1139003Sbostic * 29-Sep-82 1239003Sbostic * 1339004Sbostic * Redistribution and use in source and binary forms are permitted 1439004Sbostic * provided that the above copyright notice and this paragraph are 1539004Sbostic * duplicated in all such forms and that any documentation, 1639004Sbostic * advertising materials, and other materials related to such 1739004Sbostic * distribution and use acknowledge that the software was developed 1839004Sbostic * by the University of California, Berkeley. The name of the 1939004Sbostic * University may not be used to endorse or promote products derived 2039004Sbostic * from this software without specific prior written permission. 2139004Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 2239004Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 2339004Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2439003Sbostic */ 2539003Sbostic 2639004Sbostic #ifndef lint 2739004Sbostic char copyright[] = 2839004Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 2939004Sbostic All rights reserved.\n"; 3039004Sbostic #endif /* not lint */ 3139003Sbostic 3239004Sbostic #ifndef lint 33*39006Sbostic static char sccsid[] = "@(#)caesar.c 5.3 (Berkeley) 09/05/89"; 3439004Sbostic #endif /* not lint */ 3539004Sbostic 3639004Sbostic #include <math.h> 3739003Sbostic #include <stdio.h> 3839003Sbostic #include <ctype.h> 39*39006Sbostic #include <unistd.h> 4039003Sbostic 4139004Sbostic #define LINELENGTH 2048 4239004Sbostic #define ROTATE(ch, perm) \ 43*39006Sbostic isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \ 4439004Sbostic islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch 4539004Sbostic 46*39006Sbostic /* 47*39006Sbostic * letter frequencies (taken from some unix(tm) documentation) 48*39006Sbostic * (unix is a trademark of Bell Laboratories) 49*39006Sbostic */ 50*39006Sbostic double stdf[26] = { 51*39006Sbostic 7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04, 52*39006Sbostic 0.42, 3.81, 2.69, 5.92, 6.96, 2.91, 0.08, 6.63, 8.77, 9.68, 53*39006Sbostic 2.62, 0.81, 1.88, 0.23, 2.07, 0.06, 54*39006Sbostic }; 55*39006Sbostic 5639003Sbostic main(argc, argv) 5739004Sbostic int argc; 5839004Sbostic char **argv; 5939003Sbostic { 60*39006Sbostic extern int errno; 61*39006Sbostic register int ch, dot, i, nread, winnerdot; 6239004Sbostic register char *inbuf; 63*39006Sbostic int obs[26], try, winner; 64*39006Sbostic char *malloc(), *strerror(); 6539003Sbostic 66*39006Sbostic if (argc > 1) 67*39006Sbostic printit(argv[1]); 6839003Sbostic 6939004Sbostic if (!(inbuf = malloc(LINELENGTH))) { 7039004Sbostic (void)fprintf(stderr, "caesar: out of memory.\n"); 7139004Sbostic exit(1); 7239003Sbostic } 7339003Sbostic 7439004Sbostic /* adjust frequency table to weight low probs REAL low */ 7539004Sbostic for (i = 0; i < 26; ++i) 7639004Sbostic stdf[i] = log(stdf[i]) + log(26.0 / 100.0); 7739003Sbostic 78*39006Sbostic /* zero out observation table */ 79*39006Sbostic bzero(obs, 26 * sizeof(int)); 8039004Sbostic 81*39006Sbostic if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) { 82*39006Sbostic (void)fprintf(stderr, "caesar: %s\n", strerror(errno)); 83*39006Sbostic exit(1); 84*39006Sbostic } 85*39006Sbostic for (i = nread; i--;) { 86*39006Sbostic ch = inbuf[i]; 87*39006Sbostic if (islower(ch)) 88*39006Sbostic ++obs[ch - 'a']; 89*39006Sbostic else if (isupper(ch)) 90*39006Sbostic ++obs[ch - 'A']; 91*39006Sbostic } 9239003Sbostic 93*39006Sbostic /* 94*39006Sbostic * now "dot" the freqs with the observed letter freqs 95*39006Sbostic * and keep track of best fit 96*39006Sbostic */ 97*39006Sbostic for (try = winner = 0; try < 26; ++try) { /* += 13) { */ 98*39006Sbostic dot = 0; 99*39006Sbostic for (i = 0; i < 26; i++) 100*39006Sbostic dot += obs[i] * stdf[(i + try) % 26]; 101*39006Sbostic /* initialize winning score */ 102*39006Sbostic if (try == 0) 103*39006Sbostic winnerdot = dot; 104*39006Sbostic if (dot > winnerdot) { 105*39006Sbostic /* got a new winner! */ 106*39006Sbostic winner = try; 107*39006Sbostic winnerdot = dot; 10839003Sbostic } 109*39006Sbostic } 11039003Sbostic 111*39006Sbostic for (;;) { 112*39006Sbostic for (i = 0; i < nread; ++i) { 113*39006Sbostic ch = inbuf[i]; 11439004Sbostic putchar(ROTATE(ch, winner)); 11539004Sbostic } 116*39006Sbostic if (nread < LINELENGTH) 117*39006Sbostic break; 118*39006Sbostic if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) { 119*39006Sbostic (void)fprintf(stderr, "caesar: %s\n", strerror(errno)); 120*39006Sbostic exit(1); 121*39006Sbostic } 12239003Sbostic } 123*39006Sbostic exit(0); 12439004Sbostic } 12539003Sbostic 126*39006Sbostic printit(arg) 127*39006Sbostic char *arg; 12839004Sbostic { 129*39006Sbostic register int ch, rot; 13039003Sbostic 131*39006Sbostic if ((rot = atoi(arg)) < 0) { 132*39006Sbostic (void)fprintf(stderr, "caesar: bad rotation value.\n"); 133*39006Sbostic exit(1); 134*39006Sbostic } 13539004Sbostic while ((ch = getchar()) != EOF) 13639004Sbostic putchar(ROTATE(ch, rot)); 137*39006Sbostic exit(0); 13839003Sbostic } 139