X-Git-Url: https://git.cameronkatri.com/bsdgames-darwin.git/blobdiff_plain/a2515e35506e73e8f6422799dea7f4834cd0f558..3c48fe193d2fb7c927c2c9d1dbf76707e657a9fd:/caesar/caesar.c?ds=sidebyside diff --git a/caesar/caesar.c b/caesar/caesar.c index b9c71efc..3423602f 100644 --- a/caesar/caesar.c +++ b/caesar/caesar.c @@ -1,4 +1,4 @@ -/* $NetBSD: caesar.c,v 1.7 1998/09/13 15:27:27 hubertf Exp $ */ +/* $NetBSD: caesar.c,v 1.15 2005/05/23 23:02:30 rillig Exp $ */ /* * Copyright (c) 1989, 1993 @@ -11,6 +11,7 @@ * Stan King, John Eldridge, based on algorithm suggested by * Bob Morris * 29-Sep-82 + * Roland Illig, 2005 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,11 +21,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -51,111 +48,154 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ #if 0 static char sccsid[] = "@(#)caesar.c 8.1 (Berkeley) 5/31/93"; #else -__RCSID("$NetBSD: caesar.c,v 1.7 1998/09/13 15:27:27 hubertf Exp $"); +__RCSID("$NetBSD: caesar.c,v 1.15 2005/05/23 23:02:30 rillig Exp $"); #endif #endif /* not lint */ #include #include #include +#include #include #include #include #include #include -#define LINELENGTH 2048 -#define ROTATE(ch, perm) \ - isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \ - islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch +#define NCHARS (1 << CHAR_BIT) +#define LETTERS (26) /* * letter frequencies (taken from some unix(tm) documentation) * (unix is a trademark of Bell Laboratories) */ -double stdf[26] = { +static const unsigned char upper[LETTERS] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const unsigned char lower[LETTERS] = "abcdefghijklmnopqrstuvwxyz"; +static double stdf[LETTERS] = { 7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04, 0.42, 3.81, 2.69, 5.92, 6.96, 2.91, 0.08, 6.63, 8.77, 9.68, - 2.62, 0.81, 1.88, 0.23, 2.07, 0.06, + 2.62, 0.81, 1.88, 0.23, 2.07, 0.06 }; +static unsigned char rottbl[NCHARS]; -int main __P((int, char *[])); -void printit __P((char *)) __attribute__((__noreturn__)); -int -main(argc, argv) - int argc; - char **argv; +static void +init_rottbl(int rot) { - int ch, dot, i, nread, winnerdot; - char *inbuf; - int obs[26], try, winner; + size_t i; + + rot %= LETTERS; + + for (i = 0; i < NCHARS; i++) + rottbl[i] = (unsigned char)i; + + for (i = 0; i < LETTERS; i++) + rottbl[upper[i]] = upper[(i + rot) % LETTERS]; - winnerdot = 0; - if (argc > 1) - printit(argv[1]); + for (i = 0; i < LETTERS; i++) + rottbl[lower[i]] = lower[(i + rot) % LETTERS]; +} + +static void __attribute__((__noreturn__)) +printrot(const char *arg) +{ + int ch; + long rot; + char *endp; + + errno = 0; + rot = strtol(arg, &endp, 10); + if (*endp != '\0') { + errx(EXIT_FAILURE, "bad rotation value: %s", arg); + /* NOTREACHED */ + } + if (errno == ERANGE || rot < 0 || rot > INT_MAX) { + errx(EXIT_FAILURE, "rotation value out of range: %s", arg); + /* NOTREACHED */ + } + init_rottbl((int)rot); - if (!(inbuf = malloc(LINELENGTH))) - errx(1, "out of memory"); + while ((ch = getchar()) != EOF) { + if (putchar(rottbl[ch]) == EOF) { + err(EXIT_FAILURE, "writing to stdout"); + /* NOTREACHED */ + } + } + exit(EXIT_SUCCESS); + /* NOTREACHED */ +} + +int +main(int argc, char **argv) +{ + ssize_t i, nread, ntotal; + double dot, winnerdot; + int try, winner; + unsigned char inbuf[2048]; + unsigned int obs[NCHARS]; + + /* revoke setgid privileges */ + (void)setgid(getgid()); + + if (argc > 1) { + printrot(argv[1]); + /* NOTREACHED */ + } /* adjust frequency table to weight low probs REAL low */ - for (i = 0; i < 26; ++i) - stdf[i] = log(stdf[i]) + log(26.0 / 100.0); + for (i = 0; i < LETTERS; i++) + stdf[i] = log(stdf[i]) + log(LETTERS / 100.0); /* zero out observation table */ - memset(obs, 0, 26 * sizeof(int)); - - if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) - err(1, "reading from stdin"); - for (i = nread; i--;) { - ch = inbuf[i]; - if (islower(ch)) - ++obs[ch - 'a']; - else if (isupper(ch)) - ++obs[ch - 'A']; + (void)memset(obs, 0, sizeof(obs)); + + for (ntotal = 0; (size_t) ntotal < sizeof(inbuf); ntotal += nread) { + nread = read(STDIN_FILENO, &inbuf[ntotal], + sizeof(inbuf) - ntotal); + if (nread < 0) { + err(EXIT_FAILURE, "reading from stdin"); + /* NOTREACHED */ + } + if (nread == 0) + break; } + for (i = 0; i < ntotal; i++) + obs[inbuf[i]]++; + /* * now "dot" the freqs with the observed letter freqs * and keep track of best fit */ - for (try = winner = 0; try < 26; ++try) { /* += 13) { */ - dot = 0; - for (i = 0; i < 26; i++) - dot += obs[i] * stdf[(i + try) % 26]; - /* initialize winning score */ - if (try == 0) - winnerdot = dot; - if (dot > winnerdot) { + winner = 0; + winnerdot = 0.0; + for (try = 0; try < LETTERS; try++) { + dot = 0.0; + for (i = 0; i < LETTERS; i++) + dot += (obs[upper[i]] + obs[lower[i]]) + * stdf[(i + try) % LETTERS]; + + if (try == 0 || dot > winnerdot) { /* got a new winner! */ winner = try; winnerdot = dot; } } - - for (;;) { - for (i = 0; i < nread; ++i) { - ch = inbuf[i]; - putchar(ROTATE(ch, winner)); + init_rottbl(winner); + + while (ntotal > 0) { + for (i = 0; i < ntotal; i++) { + if (putchar(rottbl[inbuf[i]]) == EOF) { + err(EXIT_FAILURE, "writing to stdout"); + /* NOTREACHED */ + } + } + if ((ntotal = read(STDIN_FILENO, inbuf, sizeof(inbuf))) < 0) { + err(EXIT_FAILURE, "reading from stdin"); + /* NOTREACHED */ } - if (nread < LINELENGTH) - break; - if ((nread = read(STDIN_FILENO, inbuf, LINELENGTH)) < 0) - err(1, "reading from stdin"); } - exit(0); -} - -void -printit(arg) - char *arg; -{ - int ch, rot; - - if ((rot = atoi(arg)) < 0) - errx(1, "bad rotation value."); - while ((ch = getchar()) != EOF) - putchar(ROTATE(ch, rot)); - exit(0); + exit(EXIT_FAILURE); + /* NOTREACHED */ }