139003Sbostic /*
2*60756Sbostic * Copyright (c) 1989, 1993
3*60756Sbostic * The Regents of the University of California. 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 *
1342569Sbostic * %sccs.include.redist.c%
1439003Sbostic */
1539003Sbostic
1639004Sbostic #ifndef lint
17*60756Sbostic static char copyright[] =
18*60756Sbostic "@(#) Copyright (c) 1989, 1993\n\
19*60756Sbostic The Regents of the University of California. All rights reserved.\n";
2039004Sbostic #endif /* not lint */
2139003Sbostic
2239004Sbostic #ifndef lint
23*60756Sbostic static char sccsid[] = "@(#)caesar.c 8.1 (Berkeley) 05/31/93";
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
main(argc,argv)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
printit(arg)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