caesar.c revision 53210
1132718Skan/*
2132718Skan * Copyright (c) 1989, 1993
3169689Skan *	The Regents of the University of California.  All rights reserved.
4132718Skan *
5132718Skan * This code is derived from software contributed to Berkeley by
6132718Skan * Rick Adams.
7132718Skan *
8132718Skan * Authors:
9132718Skan *	Stan King, John Eldridge, based on algorithm suggested by
10132718Skan *	Bob Morris
11132718Skan * 29-Sep-82
12132718Skan *
13132718Skan * Redistribution and use in source and binary forms, with or without
14132718Skan * modification, are permitted provided that the following conditions
15132718Skan * are met:
16132718Skan * 1. Redistributions of source code must retain the above copyright
17132718Skan *    notice, this list of conditions and the following disclaimer.
18132718Skan * 2. Redistributions in binary form must reproduce the above copyright
19132718Skan *    notice, this list of conditions and the following disclaimer in the
20169689Skan *    documentation and/or other materials provided with the distribution.
21169689Skan * 3. All advertising materials mentioning features or use of this software
22132718Skan *    must display the following acknowledgement:
23132718Skan *	This product includes software developed by the University of
24132718Skan *	California, Berkeley and its contributors.
25132718Skan * 4. Neither the name of the University nor the names of its contributors
26132718Skan *    may be used to endorse or promote products derived from this software
27132718Skan *    without specific prior written permission.
28169689Skan *
29132718Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32132718Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37132718Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38132718Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39132718Skan * SUCH DAMAGE.
40132718Skan *
41132718Skan * $FreeBSD: head/games/caesar/caesar.c 53210 1999-11-16 02:58:06Z billf $
42169689Skan */
43169689Skan
44169689Skan#ifndef lint
45132718Skanstatic const char copyright[] =
46132718Skan"@(#) Copyright (c) 1989, 1993\n\
47132718Skan	The Regents of the University of California.  All rights reserved.\n";
48132718Skan#endif /* not lint */
49132718Skan
50169689Skan#ifndef lint
51132718Skan#if 0
52169689Skanstatic const char sccsid[] = "@(#)caesar.c    8.1 (Berkeley) 5/31/93";
53132718Skan#else
54132718Skanstatic const char rcsid[] =
55169689Skan  "$FreeBSD: head/games/caesar/caesar.c 53210 1999-11-16 02:58:06Z billf $";
56132718Skan#endif
57169689Skan#endif /* not lint */
58132718Skan
59169689Skan#include <errno.h>
60169689Skan#include <math.h>
61169689Skan#include <stdio.h>
62169689Skan#include <stdlib.h>
63132718Skan#include <string.h>
64132718Skan#include <ctype.h>
65132718Skan#include <unistd.h>
66132718Skan
67132718Skan#define	LINELENGTH	2048
68132718Skan#define	ROTATE(ch, perm) \
69132718Skan     isascii(ch) ? ( \
70132718Skan	isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \
71132718Skan	    islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch) : ch
72132718Skan
73132718Skan/*
74132718Skan * letter frequencies (taken from some unix(tm) documentation)
75132718Skan * (unix is a trademark of Bell Laboratories)
76132718Skan */
77double stdf[26] = {
78	7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04,
79	0.42, 3.81, 2.69, 5.92,  6.96, 2.91, 0.08, 6.63, 8.77, 9.68,
80	2.62, 0.81, 1.88, 0.23,  2.07, 0.06,
81};
82
83void printit();
84
85int
86main(argc, argv)
87	int argc;
88	char **argv;
89{
90	int ch, dot, i, nread, winnerdot = 0;
91	char *inbuf;
92	int obs[26], try, winner;
93
94	/* revoke setgid privileges */
95	setgid(getgid());
96
97	if (argc > 1)
98		printit(argv[1]);
99
100	if (!(inbuf = malloc(LINELENGTH))) {
101		(void)fprintf(stderr, "caesar: out of memory.\n");
102		exit(1);
103	}
104
105	/* adjust frequency table to weight low probs REAL low */
106	for (i = 0; i < 26; ++i)
107		stdf[i] = log(stdf[i]) + log(26.0 / 100.0);
108
109	/* zero out observation table */
110	bzero(obs, 26 * sizeof(int));
111
112	if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) {
113		(void)fprintf(stderr, "caesar: %s\n", strerror(errno));
114		exit(1);
115	}
116	for (i = nread; i--;) {
117		ch = (unsigned char) inbuf[i];
118		if (isascii(ch)) {
119			if (islower(ch))
120				++obs[ch - 'a'];
121			else if (isupper(ch))
122				++obs[ch - 'A'];
123		}
124	}
125
126	/*
127	 * now "dot" the freqs with the observed letter freqs
128	 * and keep track of best fit
129	 */
130	for (try = winner = 0; try < 26; ++try) { /* += 13) { */
131		dot = 0;
132		for (i = 0; i < 26; i++)
133			dot += obs[i] * stdf[(i + try) % 26];
134		/* initialize winning score */
135		if (try == 0)
136			winnerdot = dot;
137		if (dot > winnerdot) {
138			/* got a new winner! */
139			winner = try;
140			winnerdot = dot;
141		}
142	}
143
144	for (;;) {
145		for (i = 0; i < nread; ++i) {
146			ch = (unsigned char) inbuf[i];
147			putchar(ROTATE(ch, winner));
148		}
149		if (nread < LINELENGTH)
150			break;
151		if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) {
152			(void)fprintf(stderr, "caesar: %s\n", strerror(errno));
153			exit(1);
154		}
155	}
156	exit(0);
157}
158
159void printit(arg)
160	char *arg;
161{
162	int ch, rot;
163
164	if ((rot = atoi(arg)) < 0) {
165		(void)fprintf(stderr, "caesar: bad rotation value.\n");
166		exit(1);
167	}
168	while ((ch = getchar()) != EOF)
169		putchar(ROTATE(ch, rot));
170	exit(0);
171}
172