Home | History | Annotate | Line # | Download | only in caesar
caesar.c revision 1.13
      1  1.13      jsm /*	$NetBSD: caesar.c,v 1.13 2004/01/01 16:00:34 jsm 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.1      cgd  *
     15   1.1      cgd  * Redistribution and use in source and binary forms, with or without
     16   1.1      cgd  * modification, are permitted provided that the following conditions
     17   1.1      cgd  * are met:
     18   1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     19   1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     20   1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     21   1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     22   1.1      cgd  *    documentation and/or other materials provided with the distribution.
     23  1.12      agc  * 3. Neither the name of the University nor the names of its contributors
     24   1.1      cgd  *    may be used to endorse or promote products derived from this software
     25   1.1      cgd  *    without specific prior written permission.
     26   1.1      cgd  *
     27   1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     28   1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29   1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30   1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     31   1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32   1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     33   1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34   1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35   1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36   1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37   1.1      cgd  * SUCH DAMAGE.
     38   1.1      cgd  */
     39   1.1      cgd 
     40   1.5    lukem #include <sys/cdefs.h>
     41   1.1      cgd #ifndef lint
     42   1.5    lukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
     43   1.5    lukem 	The Regents of the University of California.  All rights reserved.\n");
     44   1.1      cgd #endif /* not lint */
     45   1.1      cgd 
     46   1.1      cgd #ifndef lint
     47   1.3      cgd #if 0
     48   1.3      cgd static char sccsid[] = "@(#)caesar.c	8.1 (Berkeley) 5/31/93";
     49   1.3      cgd #else
     50  1.13      jsm __RCSID("$NetBSD: caesar.c,v 1.13 2004/01/01 16:00:34 jsm Exp $");
     51   1.3      cgd #endif
     52   1.1      cgd #endif /* not lint */
     53   1.1      cgd 
     54   1.5    lukem #include <ctype.h>
     55   1.6    lukem #include <err.h>
     56   1.5    lukem #include <errno.h>
     57   1.1      cgd #include <math.h>
     58   1.1      cgd #include <stdio.h>
     59   1.5    lukem #include <string.h>
     60   1.5    lukem #include <stdlib.h>
     61   1.1      cgd #include <unistd.h>
     62   1.1      cgd 
     63   1.1      cgd #define	LINELENGTH	2048
     64   1.1      cgd #define	ROTATE(ch, perm) \
     65   1.1      cgd 	isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \
     66   1.1      cgd 	    islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch
     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.1      cgd double stdf[26] = {
     73   1.1      cgd 	7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04,
     74   1.1      cgd 	0.42, 3.81, 2.69, 5.92,  6.96, 2.91, 0.08, 6.63, 8.77, 9.68,
     75   1.1      cgd 	2.62, 0.81, 1.88, 0.23,  2.07, 0.06,
     76   1.1      cgd };
     77   1.1      cgd 
     78   1.5    lukem 
     79   1.5    lukem int	main __P((int, char *[]));
     80   1.9      jsm void	printit __P((const char *)) __attribute__((__noreturn__));
     81   1.5    lukem 
     82   1.5    lukem int
     83   1.1      cgd main(argc, argv)
     84   1.1      cgd 	int argc;
     85   1.1      cgd 	char **argv;
     86   1.1      cgd {
     87  1.13      jsm 	int ch, i, nread;
     88  1.13      jsm 	double dot, winnerdot;
     89   1.5    lukem 	char *inbuf;
     90   1.1      cgd 	int obs[26], try, winner;
     91   1.8  hubertf 
     92   1.8  hubertf 	/* revoke setgid privileges */
     93  1.11  mycroft 	setgid(getgid());
     94   1.1      cgd 
     95   1.5    lukem 	winnerdot = 0;
     96   1.1      cgd 	if (argc > 1)
     97   1.1      cgd 		printit(argv[1]);
     98   1.1      cgd 
     99   1.6    lukem 	if (!(inbuf = malloc(LINELENGTH)))
    100  1.10      jsm 		err(1, NULL);
    101   1.1      cgd 
    102   1.1      cgd 	/* adjust frequency table to weight low probs REAL low */
    103   1.1      cgd 	for (i = 0; i < 26; ++i)
    104   1.1      cgd 		stdf[i] = log(stdf[i]) + log(26.0 / 100.0);
    105   1.1      cgd 
    106   1.1      cgd 	/* zero out observation table */
    107   1.5    lukem 	memset(obs, 0, 26 * sizeof(int));
    108   1.1      cgd 
    109   1.6    lukem 	if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0)
    110   1.6    lukem 		err(1, "reading from stdin");
    111   1.1      cgd 	for (i = nread; i--;) {
    112   1.1      cgd 		ch = inbuf[i];
    113   1.1      cgd 		if (islower(ch))
    114   1.1      cgd 			++obs[ch - 'a'];
    115   1.1      cgd 		else if (isupper(ch))
    116   1.1      cgd 			++obs[ch - 'A'];
    117   1.1      cgd 	}
    118   1.1      cgd 
    119   1.1      cgd 	/*
    120   1.1      cgd 	 * now "dot" the freqs with the observed letter freqs
    121   1.1      cgd 	 * and keep track of best fit
    122   1.1      cgd 	 */
    123   1.1      cgd 	for (try = winner = 0; try < 26; ++try) { /* += 13) { */
    124   1.1      cgd 		dot = 0;
    125   1.1      cgd 		for (i = 0; i < 26; i++)
    126   1.1      cgd 			dot += obs[i] * stdf[(i + try) % 26];
    127   1.1      cgd 		/* initialize winning score */
    128   1.1      cgd 		if (try == 0)
    129   1.1      cgd 			winnerdot = dot;
    130   1.1      cgd 		if (dot > winnerdot) {
    131   1.1      cgd 			/* got a new winner! */
    132   1.1      cgd 			winner = try;
    133   1.1      cgd 			winnerdot = dot;
    134   1.1      cgd 		}
    135   1.1      cgd 	}
    136   1.1      cgd 
    137   1.1      cgd 	for (;;) {
    138   1.1      cgd 		for (i = 0; i < nread; ++i) {
    139   1.1      cgd 			ch = inbuf[i];
    140   1.1      cgd 			putchar(ROTATE(ch, winner));
    141   1.1      cgd 		}
    142   1.1      cgd 		if (nread < LINELENGTH)
    143   1.1      cgd 			break;
    144   1.6    lukem 		if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0)
    145   1.6    lukem 			err(1, "reading from stdin");
    146   1.1      cgd 	}
    147   1.1      cgd 	exit(0);
    148   1.1      cgd }
    149   1.1      cgd 
    150   1.5    lukem void
    151   1.1      cgd printit(arg)
    152   1.9      jsm 	const char *arg;
    153   1.1      cgd {
    154   1.5    lukem 	int ch, rot;
    155   1.1      cgd 
    156   1.6    lukem 	if ((rot = atoi(arg)) < 0)
    157   1.6    lukem 		errx(1, "bad rotation value.");
    158   1.1      cgd 	while ((ch = getchar()) != EOF)
    159   1.1      cgd 		putchar(ROTATE(ch, rot));
    160   1.1      cgd 	exit(0);
    161   1.1      cgd }
    162