Home | History | Annotate | Line # | Download | only in caesar
caesar.c revision 1.15
      1  1.15   rillig /*	$NetBSD: caesar.c,v 1.15 2005/05/23 23:02:30 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.15   rillig  *      Roland Illig, 2005
     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.1      cgd #ifndef lint
     43   1.5    lukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
     44   1.5    lukem 	The Regents of the University of California.  All rights reserved.\n");
     45   1.1      cgd #endif /* not lint */
     46   1.1      cgd 
     47   1.1      cgd #ifndef lint
     48   1.3      cgd #if 0
     49   1.3      cgd static char sccsid[] = "@(#)caesar.c	8.1 (Berkeley) 5/31/93";
     50   1.3      cgd #else
     51  1.15   rillig __RCSID("$NetBSD: caesar.c,v 1.15 2005/05/23 23:02:30 rillig Exp $");
     52   1.3      cgd #endif
     53   1.1      cgd #endif /* not lint */
     54   1.1      cgd 
     55   1.5    lukem #include <ctype.h>
     56   1.6    lukem #include <err.h>
     57   1.5    lukem #include <errno.h>
     58  1.15   rillig #include <limits.h>
     59   1.1      cgd #include <math.h>
     60   1.1      cgd #include <stdio.h>
     61   1.5    lukem #include <string.h>
     62   1.5    lukem #include <stdlib.h>
     63   1.1      cgd #include <unistd.h>
     64   1.1      cgd 
     65  1.15   rillig #define NCHARS			(1 << CHAR_BIT)
     66  1.15   rillig #define LETTERS			(26)
     67   1.1      cgd 
     68   1.1      cgd /*
     69   1.1      cgd  * letter frequencies (taken from some unix(tm) documentation)
     70   1.1      cgd  * (unix is a trademark of Bell Laboratories)
     71   1.1      cgd  */
     72  1.15   rillig static const unsigned char upper[LETTERS] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     73  1.15   rillig static const unsigned char lower[LETTERS] = "abcdefghijklmnopqrstuvwxyz";
     74  1.15   rillig static double stdf[LETTERS] = {
     75   1.1      cgd 	7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04,
     76   1.1      cgd 	0.42, 3.81, 2.69, 5.92,  6.96, 2.91, 0.08, 6.63, 8.77, 9.68,
     77  1.15   rillig 	2.62, 0.81, 1.88, 0.23,  2.07, 0.06
     78   1.1      cgd };
     79   1.1      cgd 
     80  1.15   rillig static unsigned char rottbl[NCHARS];
     81   1.5    lukem 
     82  1.15   rillig 
     83  1.15   rillig static void
     84  1.15   rillig init_rottbl(int rot)
     85  1.15   rillig {
     86  1.15   rillig 	size_t i;
     87  1.15   rillig 
     88  1.15   rillig 	rot %= LETTERS;
     89  1.15   rillig 
     90  1.15   rillig 	for (i = 0; i < NCHARS; i++)
     91  1.15   rillig 		rottbl[i] = (unsigned char)i;
     92  1.15   rillig 
     93  1.15   rillig 	for (i = 0; i < LETTERS; i++)
     94  1.15   rillig 		rottbl[upper[i]] = upper[(i + rot) % LETTERS];
     95  1.15   rillig 
     96  1.15   rillig 	for (i = 0; i < LETTERS; i++)
     97  1.15   rillig 		rottbl[lower[i]] = lower[(i + rot) % LETTERS];
     98  1.15   rillig }
     99  1.15   rillig 
    100  1.15   rillig static void __attribute__((__noreturn__))
    101  1.15   rillig printrot(const char *arg)
    102  1.15   rillig {
    103  1.15   rillig 	int ch;
    104  1.15   rillig 	long rot;
    105  1.15   rillig 	char *endp;
    106  1.15   rillig 
    107  1.15   rillig 	errno = 0;
    108  1.15   rillig 	rot = strtol(arg, &endp, 10);
    109  1.15   rillig 	if (*endp != '\0') {
    110  1.15   rillig 		errx(EXIT_FAILURE, "bad rotation value: %s", arg);
    111  1.15   rillig 		/* NOTREACHED */
    112  1.15   rillig 	}
    113  1.15   rillig 	if (errno == ERANGE || rot < 0 || rot > INT_MAX) {
    114  1.15   rillig 		errx(EXIT_FAILURE, "rotation value out of range: %s", arg);
    115  1.15   rillig 		/* NOTREACHED */
    116  1.15   rillig 	}
    117  1.15   rillig 	init_rottbl((int)rot);
    118  1.15   rillig 
    119  1.15   rillig 	while ((ch = getchar()) != EOF) {
    120  1.15   rillig 		if (putchar(rottbl[ch]) == EOF) {
    121  1.15   rillig 			err(EXIT_FAILURE, "writing to stdout");
    122  1.15   rillig 			/* NOTREACHED */
    123  1.15   rillig 		}
    124  1.15   rillig 	}
    125  1.15   rillig 	exit(EXIT_SUCCESS);
    126  1.15   rillig 	/* NOTREACHED */
    127  1.15   rillig }
    128   1.5    lukem 
    129   1.5    lukem int
    130  1.15   rillig main(int argc, char **argv)
    131   1.1      cgd {
    132  1.15   rillig 	ssize_t i, nread, ntotal;
    133  1.13      jsm 	double dot, winnerdot;
    134  1.15   rillig 	int try, winner;
    135  1.15   rillig 	unsigned char inbuf[2048];
    136  1.15   rillig 	unsigned int obs[NCHARS];
    137   1.8  hubertf 
    138   1.8  hubertf 	/* revoke setgid privileges */
    139  1.15   rillig 	(void)setgid(getgid());
    140   1.1      cgd 
    141  1.15   rillig 	if (argc > 1) {
    142  1.15   rillig 		printrot(argv[1]);
    143  1.15   rillig 		/* NOTREACHED */
    144  1.15   rillig 	}
    145   1.1      cgd 
    146   1.1      cgd 	/* adjust frequency table to weight low probs REAL low */
    147  1.15   rillig 	for (i = 0; i < LETTERS; i++)
    148  1.15   rillig 		stdf[i] = log(stdf[i]) + log(LETTERS / 100.0);
    149   1.1      cgd 
    150   1.1      cgd 	/* zero out observation table */
    151  1.15   rillig 	(void)memset(obs, 0, sizeof(obs));
    152   1.1      cgd 
    153  1.15   rillig 	for (ntotal = 0; (size_t) ntotal < sizeof(inbuf); ntotal += nread) {
    154  1.15   rillig 		nread = read(STDIN_FILENO, &inbuf[ntotal],
    155  1.15   rillig 		             sizeof(inbuf) - ntotal);
    156  1.15   rillig 		if (nread < 0) {
    157  1.15   rillig 			err(EXIT_FAILURE, "reading from stdin");
    158  1.15   rillig 			/* NOTREACHED */
    159  1.15   rillig 		}
    160  1.15   rillig 		if (nread == 0)
    161  1.15   rillig 			break;
    162   1.1      cgd 	}
    163   1.1      cgd 
    164  1.15   rillig 	for (i = 0; i < ntotal; i++)
    165  1.15   rillig 		obs[inbuf[i]]++;
    166  1.15   rillig 
    167   1.1      cgd 	/*
    168   1.1      cgd 	 * now "dot" the freqs with the observed letter freqs
    169   1.1      cgd 	 * and keep track of best fit
    170   1.1      cgd 	 */
    171  1.15   rillig 	winner = 0;
    172  1.15   rillig 	winnerdot = 0.0;
    173  1.15   rillig 	for (try = 0; try < LETTERS; try++) {
    174  1.15   rillig 		dot = 0.0;
    175  1.15   rillig 		for (i = 0; i < LETTERS; i++)
    176  1.15   rillig 			dot += (obs[upper[i]] + obs[lower[i]])
    177  1.15   rillig 			     * stdf[(i + try) % LETTERS];
    178  1.15   rillig 
    179  1.15   rillig 		if (try == 0 || dot > winnerdot) {
    180   1.1      cgd 			/* got a new winner! */
    181   1.1      cgd 			winner = try;
    182   1.1      cgd 			winnerdot = dot;
    183   1.1      cgd 		}
    184   1.1      cgd 	}
    185  1.15   rillig 	init_rottbl(winner);
    186   1.1      cgd 
    187  1.15   rillig 	while (ntotal > 0) {
    188  1.15   rillig 		for (i = 0; i < ntotal; i++) {
    189  1.15   rillig 			if (putchar(rottbl[inbuf[i]]) == EOF) {
    190  1.15   rillig 				err(EXIT_FAILURE, "writing to stdout");
    191  1.15   rillig 				/* NOTREACHED */
    192  1.15   rillig 			}
    193  1.15   rillig 		}
    194  1.15   rillig 		if ((ntotal = read(STDIN_FILENO, inbuf, sizeof(inbuf))) < 0) {
    195  1.15   rillig 			err(EXIT_FAILURE, "reading from stdin");
    196  1.15   rillig 			/* NOTREACHED */
    197   1.1      cgd 		}
    198   1.1      cgd 	}
    199  1.15   rillig 	exit(EXIT_FAILURE);
    200  1.15   rillig 	/* NOTREACHED */
    201   1.1      cgd }
    202