1 1.25 rillig /* $NetBSD: caesar.c,v 1.25 2025/09/18 22:25:04 rillig Exp $ */ 2 1.3 cgd 3 1.1 cgd /* 4 1.3 cgd * Copyright (c) 1989, 1993 5 1.3 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * This code is derived from software contributed to Berkeley by 8 1.1 cgd * Rick Adams. 9 1.1 cgd * 10 1.1 cgd * Authors: 11 1.1 cgd * Stan King, John Eldridge, based on algorithm suggested by 12 1.1 cgd * Bob Morris 13 1.1 cgd * 29-Sep-82 14 1.25 rillig * Roland Illig, 2005, 2025 15 1.1 cgd * 16 1.1 cgd * Redistribution and use in source and binary forms, with or without 17 1.1 cgd * modification, are permitted provided that the following conditions 18 1.1 cgd * are met: 19 1.1 cgd * 1. Redistributions of source code must retain the above copyright 20 1.1 cgd * notice, this list of conditions and the following disclaimer. 21 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 22 1.1 cgd * notice, this list of conditions and the following disclaimer in the 23 1.1 cgd * documentation and/or other materials provided with the distribution. 24 1.12 agc * 3. Neither the name of the University nor the names of its contributors 25 1.1 cgd * may be used to endorse or promote products derived from this software 26 1.1 cgd * without specific prior written permission. 27 1.1 cgd * 28 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 1.1 cgd * SUCH DAMAGE. 39 1.1 cgd */ 40 1.1 cgd 41 1.5 lukem #include <sys/cdefs.h> 42 1.22 lukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993\ 43 1.22 lukem The Regents of the University of California. All rights reserved."); 44 1.1 cgd 45 1.25 rillig /* @(#)caesar.c 8.1 (Berkeley) 5/31/93 */ 46 1.25 rillig __RCSID("$NetBSD: caesar.c,v 1.25 2025/09/18 22:25:04 rillig Exp $"); 47 1.1 cgd 48 1.6 lukem #include <err.h> 49 1.5 lukem #include <errno.h> 50 1.15 rillig #include <limits.h> 51 1.1 cgd #include <math.h> 52 1.1 cgd #include <stdio.h> 53 1.5 lukem #include <string.h> 54 1.5 lukem #include <stdlib.h> 55 1.1 cgd 56 1.15 rillig #define NCHARS (1 << CHAR_BIT) 57 1.15 rillig #define LETTERS (26) 58 1.1 cgd 59 1.1 cgd /* 60 1.1 cgd * letter frequencies (taken from some unix(tm) documentation) 61 1.1 cgd * (unix is a trademark of Bell Laboratories) 62 1.1 cgd */ 63 1.15 rillig static const unsigned char upper[LETTERS] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 64 1.15 rillig static const unsigned char lower[LETTERS] = "abcdefghijklmnopqrstuvwxyz"; 65 1.15 rillig static double stdf[LETTERS] = { 66 1.1 cgd 7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04, 67 1.1 cgd 0.42, 3.81, 2.69, 5.92, 6.96, 2.91, 0.08, 6.63, 8.77, 9.68, 68 1.15 rillig 2.62, 0.81, 1.88, 0.23, 2.07, 0.06 69 1.1 cgd }; 70 1.1 cgd 71 1.15 rillig static unsigned char rottbl[NCHARS]; 72 1.5 lukem 73 1.15 rillig 74 1.15 rillig static void 75 1.23 rillig init_rottbl(unsigned int rot) 76 1.15 rillig { 77 1.15 rillig 78 1.16 rillig rot %= LETTERS; /* prevent integer overflow */ 79 1.15 rillig 80 1.25 rillig for (size_t i = 0; i < NCHARS; i++) 81 1.15 rillig rottbl[i] = (unsigned char)i; 82 1.15 rillig 83 1.25 rillig for (size_t i = 0; i < LETTERS; i++) 84 1.15 rillig rottbl[upper[i]] = upper[(i + rot) % LETTERS]; 85 1.15 rillig 86 1.25 rillig for (size_t i = 0; i < LETTERS; i++) 87 1.15 rillig rottbl[lower[i]] = lower[(i + rot) % LETTERS]; 88 1.15 rillig } 89 1.15 rillig 90 1.16 rillig static void 91 1.16 rillig print_file(void) 92 1.15 rillig { 93 1.15 rillig int ch; 94 1.16 rillig 95 1.25 rillig while ((ch = getchar()) != EOF) 96 1.25 rillig if (putchar(rottbl[ch]) == EOF) 97 1.16 rillig err(EXIT_FAILURE, "<stdout>"); 98 1.16 rillig } 99 1.16 rillig 100 1.16 rillig static void 101 1.16 rillig print_array(const unsigned char *a, size_t len) 102 1.16 rillig { 103 1.16 rillig 104 1.25 rillig for (size_t i = 0; i < len; i++) 105 1.25 rillig if (putchar(rottbl[a[i]]) == EOF) 106 1.16 rillig err(EXIT_FAILURE, "<stdout>"); 107 1.16 rillig } 108 1.16 rillig 109 1.23 rillig static unsigned int 110 1.16 rillig get_rotation(const char *arg) 111 1.16 rillig { 112 1.15 rillig long rot; 113 1.15 rillig char *endp; 114 1.15 rillig 115 1.15 rillig errno = 0; 116 1.15 rillig rot = strtol(arg, &endp, 10); 117 1.21 christos if (errno == 0 && (arg[0] == '\0' || *endp != '\0')) 118 1.21 christos errno = EINVAL; 119 1.21 christos if (errno == 0 && (rot < 0 || rot > INT_MAX)) 120 1.21 christos errno = ERANGE; 121 1.21 christos if (errno) 122 1.21 christos err(EXIT_FAILURE, "Bad rotation value `%s'", arg); 123 1.23 rillig return (unsigned int)rot; 124 1.15 rillig } 125 1.5 lukem 126 1.16 rillig static void 127 1.16 rillig guess_and_rotate(void) 128 1.1 cgd { 129 1.16 rillig unsigned char inbuf[2048]; 130 1.16 rillig unsigned int obs[NCHARS]; 131 1.16 rillig size_t i, nread; 132 1.13 jsm double dot, winnerdot; 133 1.23 rillig unsigned int try, winner; 134 1.16 rillig int ch; 135 1.1 cgd 136 1.1 cgd /* adjust frequency table to weight low probs REAL low */ 137 1.15 rillig for (i = 0; i < LETTERS; i++) 138 1.15 rillig stdf[i] = log(stdf[i]) + log(LETTERS / 100.0); 139 1.1 cgd 140 1.1 cgd /* zero out observation table */ 141 1.15 rillig (void)memset(obs, 0, sizeof(obs)); 142 1.1 cgd 143 1.16 rillig for (nread = 0; nread < sizeof(inbuf); nread++) { 144 1.16 rillig if ((ch = getchar()) == EOF) 145 1.15 rillig break; 146 1.25 rillig inbuf[nread] = (unsigned char)ch; 147 1.1 cgd } 148 1.1 cgd 149 1.16 rillig for (i = 0; i < nread; i++) 150 1.15 rillig obs[inbuf[i]]++; 151 1.15 rillig 152 1.1 cgd /* 153 1.1 cgd * now "dot" the freqs with the observed letter freqs 154 1.1 cgd * and keep track of best fit 155 1.1 cgd */ 156 1.15 rillig winner = 0; 157 1.15 rillig winnerdot = 0.0; 158 1.15 rillig for (try = 0; try < LETTERS; try++) { 159 1.15 rillig dot = 0.0; 160 1.15 rillig for (i = 0; i < LETTERS; i++) 161 1.15 rillig dot += (obs[upper[i]] + obs[lower[i]]) 162 1.15 rillig * stdf[(i + try) % LETTERS]; 163 1.15 rillig 164 1.15 rillig if (try == 0 || dot > winnerdot) { 165 1.1 cgd /* got a new winner! */ 166 1.1 cgd winner = try; 167 1.1 cgd winnerdot = dot; 168 1.1 cgd } 169 1.1 cgd } 170 1.16 rillig 171 1.15 rillig init_rottbl(winner); 172 1.16 rillig print_array(inbuf, nread); 173 1.16 rillig print_file(); 174 1.16 rillig } 175 1.1 cgd 176 1.16 rillig int 177 1.16 rillig main(int argc, char **argv) 178 1.16 rillig { 179 1.18 rillig 180 1.25 rillig if (argc == 1) 181 1.16 rillig guess_and_rotate(); 182 1.25 rillig else if (argc == 2) { 183 1.16 rillig init_rottbl(get_rotation(argv[1])); 184 1.16 rillig print_file(); 185 1.16 rillig } else { 186 1.17 rillig (void)fprintf(stderr, "usage: caesar [rotation]\n"); 187 1.16 rillig exit(EXIT_FAILURE); 188 1.16 rillig } 189 1.16 rillig 190 1.25 rillig if (ferror(stdin) != 0) 191 1.24 rillig errx(EXIT_FAILURE, "<stdin>: read error"); 192 1.16 rillig 193 1.16 rillig (void)fflush(stdout); 194 1.25 rillig if (ferror(stdout) != 0) 195 1.24 rillig errx(EXIT_FAILURE, "<stdout>: write error"); 196 1.16 rillig 197 1.16 rillig return 0; 198 1.1 cgd } 199