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 * 13*42569Sbostic * %sccs.include.redist.c% 1439003Sbostic */ 1539003Sbostic 1639004Sbostic #ifndef lint 1739004Sbostic char copyright[] = 1839004Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 1939004Sbostic All rights reserved.\n"; 2039004Sbostic #endif /* not lint */ 2139003Sbostic 2239004Sbostic #ifndef lint 23*42569Sbostic static char sccsid[] = "@(#)caesar.c 5.4 (Berkeley) 06/01/90"; 2439004Sbostic #endif /* not lint */ 2539004Sbostic 2639004Sbostic #include <math.h> 2739003Sbostic #include <stdio.h> 2839003Sbostic #include <ctype.h> 2939006Sbostic #include <unistd.h> 3039003Sbostic 3139004Sbostic #define LINELENGTH 2048 3239004Sbostic #define ROTATE(ch, perm) \ 3339006Sbostic isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \ 3439004Sbostic islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch 3539004Sbostic 3639006Sbostic /* 3739006Sbostic * letter frequencies (taken from some unix(tm) documentation) 3839006Sbostic * (unix is a trademark of Bell Laboratories) 3939006Sbostic */ 4039006Sbostic double stdf[26] = { 4139006Sbostic 7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04, 4239006Sbostic 0.42, 3.81, 2.69, 5.92, 6.96, 2.91, 0.08, 6.63, 8.77, 9.68, 4339006Sbostic 2.62, 0.81, 1.88, 0.23, 2.07, 0.06, 4439006Sbostic }; 4539006Sbostic 4639003Sbostic main(argc, argv) 4739004Sbostic int argc; 4839004Sbostic char **argv; 4939003Sbostic { 5039006Sbostic extern int errno; 5139006Sbostic register int ch, dot, i, nread, winnerdot; 5239004Sbostic register char *inbuf; 5339006Sbostic int obs[26], try, winner; 5439006Sbostic char *malloc(), *strerror(); 5539003Sbostic 5639006Sbostic if (argc > 1) 5739006Sbostic printit(argv[1]); 5839003Sbostic 5939004Sbostic if (!(inbuf = malloc(LINELENGTH))) { 6039004Sbostic (void)fprintf(stderr, "caesar: out of memory.\n"); 6139004Sbostic exit(1); 6239003Sbostic } 6339003Sbostic 6439004Sbostic /* adjust frequency table to weight low probs REAL low */ 6539004Sbostic for (i = 0; i < 26; ++i) 6639004Sbostic stdf[i] = log(stdf[i]) + log(26.0 / 100.0); 6739003Sbostic 6839006Sbostic /* zero out observation table */ 6939006Sbostic bzero(obs, 26 * sizeof(int)); 7039004Sbostic 7139006Sbostic if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) { 7239006Sbostic (void)fprintf(stderr, "caesar: %s\n", strerror(errno)); 7339006Sbostic exit(1); 7439006Sbostic } 7539006Sbostic for (i = nread; i--;) { 7639006Sbostic ch = inbuf[i]; 7739006Sbostic if (islower(ch)) 7839006Sbostic ++obs[ch - 'a']; 7939006Sbostic else if (isupper(ch)) 8039006Sbostic ++obs[ch - 'A']; 8139006Sbostic } 8239003Sbostic 8339006Sbostic /* 8439006Sbostic * now "dot" the freqs with the observed letter freqs 8539006Sbostic * and keep track of best fit 8639006Sbostic */ 8739006Sbostic for (try = winner = 0; try < 26; ++try) { /* += 13) { */ 8839006Sbostic dot = 0; 8939006Sbostic for (i = 0; i < 26; i++) 9039006Sbostic dot += obs[i] * stdf[(i + try) % 26]; 9139006Sbostic /* initialize winning score */ 9239006Sbostic if (try == 0) 9339006Sbostic winnerdot = dot; 9439006Sbostic if (dot > winnerdot) { 9539006Sbostic /* got a new winner! */ 9639006Sbostic winner = try; 9739006Sbostic winnerdot = dot; 9839003Sbostic } 9939006Sbostic } 10039003Sbostic 10139006Sbostic for (;;) { 10239006Sbostic for (i = 0; i < nread; ++i) { 10339006Sbostic ch = inbuf[i]; 10439004Sbostic putchar(ROTATE(ch, winner)); 10539004Sbostic } 10639006Sbostic if (nread < LINELENGTH) 10739006Sbostic break; 10839006Sbostic if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) { 10939006Sbostic (void)fprintf(stderr, "caesar: %s\n", strerror(errno)); 11039006Sbostic exit(1); 11139006Sbostic } 11239003Sbostic } 11339006Sbostic exit(0); 11439004Sbostic } 11539003Sbostic 11639006Sbostic printit(arg) 11739006Sbostic char *arg; 11839004Sbostic { 11939006Sbostic register int ch, rot; 12039003Sbostic 12139006Sbostic if ((rot = atoi(arg)) < 0) { 12239006Sbostic (void)fprintf(stderr, "caesar: bad rotation value.\n"); 12339006Sbostic exit(1); 12439006Sbostic } 12539004Sbostic while ((ch = getchar()) != EOF) 12639004Sbostic putchar(ROTATE(ch, rot)); 12739006Sbostic exit(0); 12839003Sbostic } 129