1*ab9f6680Sschwarze /* $OpenBSD: caesar.c,v 1.21 2019/05/15 15:59:24 schwarze Exp $ */
2df930be7Sderaadt
3df930be7Sderaadt /*
4df930be7Sderaadt * Copyright (c) 1989, 1993
5df930be7Sderaadt * The Regents of the University of California. All rights reserved.
6df930be7Sderaadt *
7df930be7Sderaadt * This code is derived from software contributed to Berkeley by
8df930be7Sderaadt * Rick Adams.
9df930be7Sderaadt *
10df930be7Sderaadt * Authors:
11df930be7Sderaadt * Stan King, John Eldridge, based on algorithm suggested by
12df930be7Sderaadt * Bob Morris
13df930be7Sderaadt * 29-Sep-82
14df930be7Sderaadt *
15df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
16df930be7Sderaadt * modification, are permitted provided that the following conditions
17df930be7Sderaadt * are met:
18df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
19df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
20df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
21df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
22df930be7Sderaadt * documentation and/or other materials provided with the distribution.
237a09557bSmillert * 3. Neither the name of the University nor the names of its contributors
24df930be7Sderaadt * may be used to endorse or promote products derived from this software
25df930be7Sderaadt * without specific prior written permission.
26df930be7Sderaadt *
27df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37df930be7Sderaadt * SUCH DAMAGE.
38df930be7Sderaadt */
39df930be7Sderaadt
40df930be7Sderaadt #include <ctype.h>
41986c0edfSderaadt #include <err.h>
42e0232237Sniklas #include <errno.h>
435dc4a87cSpjanzen #include <math.h>
445dc4a87cSpjanzen #include <stdio.h>
455dc4a87cSpjanzen #include <string.h>
465dc4a87cSpjanzen #include <stdlib.h>
475dc4a87cSpjanzen #include <unistd.h>
48df930be7Sderaadt
49df930be7Sderaadt #define LINELENGTH 2048
50df930be7Sderaadt #define ROTATE(ch, perm) \
51df930be7Sderaadt isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \
52df930be7Sderaadt islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch
53df930be7Sderaadt
54df930be7Sderaadt /*
555b2e6243Stedu * letter frequencies
56df930be7Sderaadt */
57df930be7Sderaadt double stdf[26] = {
585b2e6243Stedu 8.1, 1.4, 2.7, 3.8, 13.0, 2.9, 2.0, 5.2, 6.3, 0.13,
595b2e6243Stedu 0.4, 3.4, 2.5, 7.1, 7.9, 1.9, 0.11, 6.8, 6.1, 10.5,
605b2e6243Stedu 2.4, 0.9, 1.5, 0.15, 1.9, 0.07
61df930be7Sderaadt };
62df930be7Sderaadt
63b9a3a871Sschwarze __dead void printit(int);
64986c0edfSderaadt
65986c0edfSderaadt int
main(int argc,char * argv[])66a5ca3416Sderaadt main(int argc, char *argv[])
67df930be7Sderaadt {
6861f9e11aSotto int ch, i, nread;
69466e81dfStb extern char *__progname;
70dd8b6bb4Smestre const char *errstr;
71466e81dfStb char *inbuf;
72df930be7Sderaadt int obs[26], try, winner;
7361f9e11aSotto double dot, winnerdot;
74df930be7Sderaadt
75673e924cSdoug if (pledge("stdio", NULL) == -1)
76673e924cSdoug err(1, "pledge");
77673e924cSdoug
78986c0edfSderaadt /* check to see if we were called as rot13 */
79466e81dfStb if (strcmp(__progname, "rot13") == 0)
80986c0edfSderaadt printit(13);
81986c0edfSderaadt
825dc4a87cSpjanzen if (argc > 1) {
83*ab9f6680Sschwarze i = strtonum(argv[1], -25, 25, &errstr);
84dd8b6bb4Smestre if (errstr)
85dd8b6bb4Smestre errx(1, "rotation is %s: %s", errstr, argv[1]);
865dc4a87cSpjanzen else
87dd8b6bb4Smestre printit(i);
885dc4a87cSpjanzen }
895dc4a87cSpjanzen
90986c0edfSderaadt if (!(inbuf = malloc(LINELENGTH)))
915b71d505Spjanzen err(1, NULL);
92986c0edfSderaadt
93df930be7Sderaadt /* adjust frequency table to weight low probs REAL low */
94df930be7Sderaadt for (i = 0; i < 26; ++i)
95df930be7Sderaadt stdf[i] = log(stdf[i]) + log(26.0 / 100.0);
96df930be7Sderaadt
97df930be7Sderaadt /* zero out observation table */
98986c0edfSderaadt memset(obs, 0, 26 * sizeof(int));
99df930be7Sderaadt
100986c0edfSderaadt nread = 0;
101986c0edfSderaadt while ((nread < LINELENGTH) && ((ch = getchar()) != EOF)) {
102986c0edfSderaadt inbuf[nread++] = ch;
103df930be7Sderaadt if (islower(ch))
104df930be7Sderaadt ++obs[ch - 'a'];
105df930be7Sderaadt else if (isupper(ch))
106df930be7Sderaadt ++obs[ch - 'A'];
107df930be7Sderaadt }
108df930be7Sderaadt
109df930be7Sderaadt /*
110df930be7Sderaadt * now "dot" the freqs with the observed letter freqs
111df930be7Sderaadt * and keep track of best fit
112df930be7Sderaadt */
1135dc4a87cSpjanzen winnerdot = 0;
114df930be7Sderaadt for (try = winner = 0; try < 26; ++try) { /* += 13) { */
115df930be7Sderaadt dot = 0;
116df930be7Sderaadt for (i = 0; i < 26; i++)
117df930be7Sderaadt dot += obs[i] * stdf[(i + try) % 26];
118df930be7Sderaadt if (dot > winnerdot) {
119df930be7Sderaadt /* got a new winner! */
120df930be7Sderaadt winner = try;
121df930be7Sderaadt winnerdot = dot;
122df930be7Sderaadt }
123df930be7Sderaadt }
124df930be7Sderaadt
125986c0edfSderaadt /* dump the buffer before calling printit */
126df930be7Sderaadt for (i = 0; i < nread; ++i) {
127df930be7Sderaadt ch = inbuf[i];
128df930be7Sderaadt putchar(ROTATE(ch, winner));
129df930be7Sderaadt }
130986c0edfSderaadt printit(winner);
131df930be7Sderaadt }
132df930be7Sderaadt
133986c0edfSderaadt void
printit(int rot)134a5ca3416Sderaadt printit(int rot)
135df930be7Sderaadt {
13697419aa0Spjanzen int ch;
137df930be7Sderaadt
138*ab9f6680Sschwarze if (rot < 0)
139*ab9f6680Sschwarze rot = rot + 26;
140df930be7Sderaadt while ((ch = getchar()) != EOF)
141df930be7Sderaadt putchar(ROTATE(ch, rot));
142df930be7Sderaadt exit(0);
143df930be7Sderaadt }
144