]> granicus.if.org Git - fortune-mod/blobdiff - fortune-mod/fortune/fortune.c
Re-implement BSD-style -o suffix support
[fortune-mod] / fortune-mod / fortune / fortune.c
index a35156a78394c904f601acd680b93f7a82719c0d..d68e523bd83f2ad2266cc0af83d28f2d620268d5 100644 (file)
  * Added to debian by Alastair McKinstry, <mckinstry@computer.org>, 2002-07-31
  */
 
-#if 0 /* comment out the stuff here, and get rid of silly warnings */
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1986, 1993\n\
-        The Regents of the University of California.  All rights reserved.\n";
-
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)fortune.c   8.1 (Berkeley) 5/31/93";
-
-#else
-static char rcsid[] = "$NetBSD: fortune.c,v 1.8 1995/03/23 08:28:40 cgd Exp $";
-
-#endif
-#endif /* not lint */
-#endif /* killing warnings */
-
 #define PROGRAM_NAME "fortune-mod"
 
+#include "config.h"
 #include "fortune-mod-common.h"
 
 #include <dirent.h>
@@ -105,11 +87,18 @@ static char rcsid[] = "$NetBSD: fortune.c,v 1.8 1995/03/23 08:28:40 cgd Exp $";
 #include <assert.h>
 #include <errno.h>
 #include <locale.h>
+
 #ifndef _WIN32
+
 #include <langinfo.h>
 #define O_BINARY 0
+
+#ifdef HAVE_RECODE_H
 #define WITH_RECODE
 #endif
+
+#endif
+
 #ifdef WITH_RECODE
 #include <recode.h>
 #endif
@@ -117,17 +106,6 @@ static char rcsid[] = "$NetBSD: fortune.c,v 1.8 1995/03/23 08:28:40 cgd Exp $";
 #ifdef HAVE_REGEX_H
 #include <regex.h>
 #endif
-#ifdef HAVE_REGEXP_H
-#include <regexp.h>
-#endif
-#ifdef HAVE_RX_H
-#include <rx.h>
-#endif
-
-#include "config.h"
-
-#define TRUE 1
-#define FALSE 0
 
 #define MINW 6   /* minimum wait if desired */
 #define CPERS 20 /* # of chars for each sec */
@@ -138,7 +116,9 @@ static char rcsid[] = "$NetBSD: fortune.c,v 1.8 1995/03/23 08:28:40 cgd Exp $";
 #ifdef DEBUG
 #define DPRINTF(l, x)                                                          \
     if (Debug >= l)                                                            \
-        fprintf x;
+    {                                                                          \
+        fprintf x;                                                             \
+    }
 #else
 #define DPRINTF(l, x)
 #endif
@@ -161,29 +141,38 @@ typedef struct fd
     struct fd *next, *prev;
 } FILEDESC;
 
-static char *env_lang;
+static const char *env_lang = NULL;
 
-static bool Found_one;           /* did we find a match? */
-static bool Find_files = FALSE;  /* just find a list of proper fortune files */
-static bool Wait = FALSE;        /* wait desired after fortune */
-static bool Short_only = FALSE;  /* short fortune desired */
-static bool Long_only = FALSE;   /* long fortune desired */
-static bool Offend = FALSE;      /* offensive fortunes only */
-static bool All_forts = FALSE;   /* any fortune allowed */
-static bool Equal_probs = FALSE; /* scatter un-allocated prob equally */
-static bool Show_filename = FALSE;
-static bool No_recode = FALSE; /* Do we want to stop recoding from occuring */
+static bool Find_files = false;  /* just find a list of proper fortune files */
+static bool Wait = false;        /* wait desired after fortune */
+static bool Short_only = false;  /* short fortune desired */
+static bool Long_only = false;   /* long fortune desired */
+static bool Offend = false;      /* offensive fortunes only */
+static bool All_forts = false;   /* any fortune allowed */
+static bool Equal_probs = false; /* scatter un-allocated prob equally */
+static bool Show_filename = false;
+static bool No_recode = false; /* Do we want to stop recoding from occuring */
 
 static bool ErrorMessage =
-    FALSE; /* Set to true if an error message has been displayed */
+    false; /* Set to true if an error message has been displayed */
 
-#ifndef NO_REGEX
-static bool Match = FALSE; /* dump fortunes matching a pattern */
+#ifdef POSIX_REGEX
+#define WITH_REGEX
+#define RE_COMP(p) regcomp(&Re_pat, (p), REG_NOSUB)
+#define BAD_COMP(f) ((f) != 0)
+#define RE_EXEC(p) (regexec(&Re_pat, (p), 0, NULL, 0) == 0)
+
+static regex_t Re_pat;
+#else
+#define NO_REGEX
+#endif /* POSIX_REGEX */
 
+#ifdef WITH_REGEX
+static bool Match = false; /* dump fortunes matching a pattern */
 #endif
-#ifdef DEBUG
-static bool Debug = FALSE; /* print debug messages */
 
+#ifdef DEBUG
+static bool Debug = false; /* print debug messages */
 #endif
 
 static unsigned char *Fortbuf = NULL; /* fortune buffer for -m */
@@ -200,30 +189,23 @@ static FILEDESC *Fortfile;         /* Fortune file to use */
 
 static STRFILE Noprob_tbl; /* sum of data for all no prob files */
 
-#ifdef POSIX_REGEX
-#define RE_COMP(p) regcomp(&Re_pat, (p), REG_NOSUB)
-#define BAD_COMP(f) ((f) != 0)
-#define RE_EXEC(p) (regexec(&Re_pat, (p), 0, NULL, 0) == 0)
-
-static regex_t Re_pat;
-#else
-#define NO_REGEX
-#endif /* POSIX_REGEX */
-
 #ifdef WITH_RECODE
 static RECODE_REQUEST request;
 static RECODE_OUTER outer;
+static inline char *my_recode_string(const char *s)
+{
+    return recode_string(request, (const char *)s);
+}
+#else
+static inline char *my_recode_string(const char *s) { return strdup(s); }
 #endif
 
-int add_dir(register FILEDESC *);
+static int add_dir(FILEDESC *);
 
-static unsigned long my_random(unsigned long base)
+static unsigned long my_random(const unsigned long base)
 {
-    FILE *fp;
     unsigned long long l = 0;
-    char *hard_coded_val;
-
-    hard_coded_val = getenv("FORTUNE_MOD_RAND_HARD_CODED_VALS");
+    char *hard_coded_val = getenv("FORTUNE_MOD_RAND_HARD_CODED_VALS");
     if (hard_coded_val)
     {
         return ((unsigned long)atol(hard_coded_val) % base);
@@ -232,7 +214,7 @@ static unsigned long my_random(unsigned long base)
     {
         goto fallback;
     }
-    fp = fopen("/dev/urandom", "rb");
+    FILE *const fp = fopen("/dev/urandom", "rb");
     if (!fp)
     {
         goto fallback;
@@ -245,40 +227,40 @@ static unsigned long my_random(unsigned long base)
     fclose(fp);
     return l % base;
 fallback:
-    return random() % base;
+    return (((unsigned long)random()) % base);
 }
 
 static char *program_version(void)
 {
     static char buf[BUFSIZ];
-    (void)sprintf(buf, "%s version %s", PROGRAM_NAME, VERSION);
+    (void)snprintf(buf, sizeof(buf), "%s version %s", PROGRAM_NAME, VERSION);
     return buf;
 }
 
 static void __attribute__((noreturn)) usage(void)
 {
     (void)fprintf(stderr, "%s\n", program_version());
-    (void)fprintf(stderr, "fortune [-a");
+    (void)fprintf(stderr, "%s", "fortune [-a");
 #ifdef DEBUG
-    (void)fprintf(stderr, "D");
+    (void)fprintf(stderr, "%s", "D");
 #endif /* DEBUG */
-    (void)fprintf(stderr, "f");
-#ifndef NO_REGEX
-    (void)fprintf(stderr, "i");
-#endif /* NO_REGEX */
-    (void)fprintf(stderr, "l");
+    (void)fprintf(stderr, "%s", "f");
+#ifdef WITH_REGEX
+    (void)fprintf(stderr, "%s", "i");
+#endif
+    (void)fprintf(stderr, "%s", "l");
 #ifndef NO_OFFENSIVE
-    (void)fprintf(stderr, "o");
+    (void)fprintf(stderr, "%s", "o");
+#endif
+    (void)fprintf(stderr, "%s", "sw]");
+#ifdef WITH_REGEX
+    (void)fprintf(stderr, "%s", " [-m pattern]");
 #endif
-    (void)fprintf(stderr, "sw]");
-#ifndef NO_REGEX
-    (void)fprintf(stderr, " [-m pattern]");
-#endif /* NO_REGEX */
-    (void)fprintf(stderr, " [-n number] [ [#%%] file/directory/all]\n");
+    (void)fprintf(stderr, "%s", " [-n number] [ [#%] file/directory/all]\n");
     exit(1);
 }
 
-#define STR(str) ((str) == NULL ? "NULL" : (str))
+#define STR(str) ((!str) ? "NULL" : (str))
 
 /*
  * calc_equal_probs:
@@ -287,11 +269,9 @@ static void __attribute__((noreturn)) usage(void)
  */
 static void calc_equal_probs(void)
 {
-    FILEDESC *fiddlylist;
-
     Num_files = Num_kids = 0;
-    fiddlylist = File_list;
-    while (fiddlylist != NULL)
+    FILEDESC *fiddlylist = File_list;
+    while (fiddlylist)
     {
         Num_files++;
         Num_kids += fiddlylist->num_children;
@@ -303,122 +283,123 @@ static void calc_equal_probs(void)
  * print_list:
  *      Print out the actual list, recursively.
  */
-static void print_list(register FILEDESC *list, int lev)
+static void print_list(FILEDESC *list, int lev)
 {
-    while (list != NULL)
+    while (list)
     {
         fprintf(stderr, "%*s", lev * 4, "");
         if (list->percent == NO_PROB)
+        {
             if (!Equal_probs)
+            {
                 /* This, with some changes elsewhere, gives proper percentages
                  * for every case fprintf(stderr, "___%%"); */
                 fprintf(stderr, "%5.2f%%",
                     (100.0 - Spec_prob) * list->tbl.str_numstr /
                         Noprob_tbl.str_numstr);
+            }
             else if (lev == 0)
+            {
                 fprintf(stderr, "%5.2f%%", 100.0 / Num_files);
+            }
             else
+            {
                 fprintf(stderr, "%5.2f%%", 100.0 / Num_kids);
+            }
+        }
         else
+        {
             fprintf(stderr, "%5.2f%%", 1.0 * list->percent);
+        }
         fprintf(stderr, " %s", STR(list->name));
         DPRINTF(1, (stderr, " (%s, %s, %s)\n", STR(list->path),
                        STR(list->datfile), STR(list->posfile)));
         putc('\n', stderr);
-        if (list->child != NULL)
+        if (list->child)
+        {
             print_list(list->child, lev + 1);
+        }
         list = list->next;
     }
 }
 
-#ifndef NO_REGEX
+#ifdef WITH_REGEX
 /*
  * conv_pat:
  *      Convert the pattern to an ignore-case equivalent.
  */
-static char *conv_pat(register char *orig)
+static char *conv_pat(const char *const orig_str)
 {
-    register char *sp;
-    register unsigned int cnt;
-    register char *new;
+    const char *sp;
+    char *new_buf;
 
-    cnt = 1; /* allow for '\0' */
-    for (sp = orig; *sp != '\0'; sp++)
+    size_t cnt = 1; /* allow for '\0' */
+    for (sp = orig_str; *sp != '\0'; sp++)
+    {
+        const size_t prev_cnt = cnt;
         if (isalpha(*sp))
+        {
             cnt += 4;
+        }
         else
-            cnt++;
-    if ((new = malloc(cnt)) == NULL)
+        {
+            ++cnt;
+        }
+        if (prev_cnt >= cnt)
+        {
+            fprintf(stderr, "%s",
+                "pattern too long for ignoring case; overflow!\n");
+            exit(1);
+        }
+    }
+    if (!(new_buf = malloc(cnt)))
     {
-        fprintf(stderr, "pattern too long for ignoring case\n");
+        fprintf(stderr, "%s", "pattern too long for ignoring case\n");
         exit(1);
     }
 
-    for (sp = new; *orig != '\0'; orig++)
+    char *dest_ptr;
+    const char *orig = orig_str;
+    for (dest_ptr = new_buf; *orig != '\0'; ++orig)
     {
         if (islower(*orig))
         {
-            *sp++ = '[';
-            *sp++ = *orig;
-            *sp++ = (char)toupper(*orig);
-            *sp++ = ']';
+            *dest_ptr++ = '[';
+            *dest_ptr++ = *orig;
+            *dest_ptr++ = (char)toupper(*orig);
+            *dest_ptr++ = ']';
         }
         else if (isupper(*orig))
         {
-            *sp++ = '[';
-            *sp++ = *orig;
-            *sp++ = (char)tolower(*orig);
-            *sp++ = ']';
+            *dest_ptr++ = '[';
+            *dest_ptr++ = *orig;
+            *dest_ptr++ = (char)tolower(*orig);
+            *dest_ptr++ = ']';
         }
         else
-            *sp++ = *orig;
+        {
+            *dest_ptr++ = *orig;
+        }
     }
-    *sp = '\0';
-    return new;
+    *dest_ptr = '\0';
+    return new_buf;
 }
-#endif /* NO_REGEX */
+#endif
 
 /*
  * do_malloc:
  *      Do a malloc, checking for NULL return.
  */
-static void *do_malloc(size_t size)
+static void *do_malloc(const size_t size)
 {
-    void *new;
+    void *new_buf = malloc(size);
 
-    if ((new = malloc(size)) == NULL)
+    if (!new_buf)
     {
-        (void)fprintf(stderr, "fortune: out of memory.\n");
+        (void)fprintf(stderr, "%s", "fortune: out of memory.\n");
         exit(1);
     }
-    return new;
-}
-
-/*
- * do_free:
- *      Free malloc'ed space, if any.
- */
-static void do_free(void *ptr)
-{
-    if (ptr != NULL)
-        free(ptr);
-}
-
-/*
- * copy:
- *      Return a malloc()'ed copy of the string
- */
-static char *copy(char *str, unsigned int len)
-{
-    char *new, *sp;
-
-    new = do_malloc(len + 1);
-    sp = new;
-    do
-    {
-        *sp++ = *str;
-    } while (*str++);
-    return new;
+    return new_buf;
 }
 
 /*
@@ -427,15 +408,15 @@ static char *copy(char *str, unsigned int len)
  */
 static FILEDESC *new_fp(void)
 {
-    register FILEDESC *fp;
+    FILEDESC *fp;
 
-    fp = (FILEDESC *)do_malloc(sizeof *fp);
+    fp = do_malloc(sizeof *fp);
     fp->datfd = -1;
     fp->pos = POS_UNKNOWN;
     fp->inf = NULL;
     fp->fd = -1;
     fp->percent = NO_PROB;
-    fp->read_tbl = FALSE;
+    fp->read_tbl = false;
     fp->tbl.str_version = 0;
     fp->tbl.str_numstr = 0;
     fp->tbl.str_longlen = 0;
@@ -471,37 +452,39 @@ static inline void debugprint(const char *msg, ...)
 #endif
 /*
  * is_dir:
- *      Return TRUE if the file is a directory, FALSE otherwise.
+ *      Return true if the file is a directory, false otherwise.
  */
 static int is_dir(const char *const file)
 {
-    auto struct stat sbuf;
+    struct stat sbuf;
 
     if (stat(file, &sbuf) < 0)
     {
         debugprint("is_dir failed for file=<%s>\n", file);
         return -1;
     }
-    const bool ret = ((sbuf.st_mode & S_IFDIR) ? true : false);
+    const bool ret = (S_ISDIR(sbuf.st_mode) ? true : false);
     debugprint("is_dir for file=<%s> gave ret=<%d>\n", file, ret);
     return ret;
 }
 
 /*
  * is_existant:
- *      Return TRUE if the file exists, FALSE otherwise.
+ *      Return true if the file exists, false otherwise.
  */
 static int is_existant(char *file)
 {
     struct stat staat;
 
     if (stat(file, &staat) == 0)
-        return TRUE;
+    {
+        return true;
+    }
     switch (errno)
     {
     case ENOENT:
     case ENOTDIR:
-        return FALSE;
+        return false;
     default:
         perror("fortune: bad juju in is_existant");
         exit(1);
@@ -510,56 +493,65 @@ static int is_existant(char *file)
 
 /*
  * is_fortfile:
- *      Return TRUE if the file is a fortune database file.  We try and
+ *      Return true if the file is a fortune database file.  We try and
  *      exclude files without reading them if possible to avoid
  *      overhead.  Files which start with ".", or which have "illegal"
  *      suffixes, as contained in suflist[], are ruled out.
  */
-static int is_fortfile(char *file, char **datp)
+static int is_fortfile(const char *const file, char **datp)
 {
-    register int i;
-    register char *sp;
-    register char *datfile;
+    const char *sp = strrchr(file, '/');
     static const char *suflist[] = {/* list of "illegal" suffixes" */
         "dat", "pos", "c", "h", "p", "i", "f", "pas", "ftn", "ins.c", "ins,pas",
         "ins.ftn", "sml", NULL};
 
     DPRINTF(2, (stderr, "is_fortfile(%s) returns ", file));
 
-    if ((sp = strrchr(file, '/')) == NULL)
+    if (!sp)
+    {
         sp = file;
+    }
     else
+    {
         sp++;
+    }
     if (*sp == '.')
     {
-        DPRINTF(2, (stderr, "FALSE (file starts with '.')\n"));
-        return FALSE;
+        DPRINTF(2, (stderr, "%s", "false (file starts with '.')\n"));
+        return false;
     }
-    if ((sp = strrchr(sp, '.')) != NULL)
+    if ((sp = strrchr(sp, '.')))
     {
         sp++;
-        for (i = 0; suflist[i] != NULL; i++)
+        for (int i = 0; suflist[i]; ++i)
+        {
             if (strcmp(sp, suflist[i]) == 0)
             {
-                DPRINTF(2, (stderr, "FALSE (file has suffix \".%s\")\n", sp));
-                return FALSE;
+                DPRINTF(2, (stderr, "false (file has suffix \".%s\")\n", sp));
+                return false;
             }
+        }
     }
 
-    datfile = copy(file, (unsigned int)(strlen(file) + 4)); /* +4 for ".dat" */
-    strcat(datfile, ".dat");
+    const size_t do_len = (strlen(file) + 6);
+    char *const datfile = do_malloc(do_len + 1);
+    snprintf(datfile, do_len, "%s.dat", file);
     if (access(datfile, R_OK) < 0)
     {
         free(datfile);
-        DPRINTF(2, (stderr, "FALSE (no \".dat\" file)\n"));
-        return FALSE;
+        DPRINTF(2, (stderr, "%s", "false (no \".dat\" file)\n"));
+        return false;
     }
-    if (datp != NULL)
+    if (datp)
+    {
         *datp = datfile;
+    }
     else
+    {
         free(datfile);
-    DPRINTF(2, (stderr, "TRUE\n"));
-    return TRUE;
+    }
+    DPRINTF(2, (stderr, "%s", "true\n"));
+    return true;
 }
 
 static bool path_is_absolute(const char *const path)
@@ -576,45 +568,48 @@ static bool path_is_absolute(const char *const path)
 #endif
     return false;
 }
+
+static int open4read(const char *const path)
+{
+    return open(path, O_RDONLY | O_BINARY);
+}
+
 /*
  * add_file:
  *      Add a file to the file list.
  */
-static int add_file(int percent, register const char *file, const char *dir,
+#define GCC_SNPRINTF_MARGIN 10
+static int add_file(int percent, const char *file, const char *dir,
     FILEDESC **head, FILEDESC **tail, FILEDESC *parent)
 {
-    register FILEDESC *fp;
-    register int fd = -1;
-    register char *path, *testpath;
-    register bool was_malloc;
-    auto char *sp;
-    auto bool found;
+    FILEDESC *fp;
+    int fd = -1;
+    char *path;
+    char *sp;
     struct stat statbuf;
 
-    if (dir == NULL)
+    if (!dir)
     {
         path = strdup(file);
-        was_malloc = TRUE;
     }
     else
     {
-        path = do_malloc((unsigned int)(strlen(dir) + strlen(file) + 2));
-        (void)strcat(strcat(strcpy(path, dir), "/"), file);
-        was_malloc = TRUE;
+        const size_t do_len =
+            (strlen(dir) + strlen(file) + (2 + GCC_SNPRINTF_MARGIN));
+        path = do_malloc(do_len + 1);
+        snprintf(path, do_len, "%s/%s", dir, file);
     }
     if (*path == '/' &&
         !is_existant(path)) /* If doesn't exist, don't do anything. */
     {
-        if (was_malloc)
-            free(path);
-        return FALSE;
+        free(path);
+        return false;
     }
     const int isdir = is_dir(path);
-    if ((isdir > 0 && parent != NULL) || (isdir < 0))
+    if ((isdir > 0 && parent) || (isdir < 0))
     {
-        if (was_malloc)
-            free(path);
-        return FALSE; /* don't recurse */
+        free(path);
+        return false; /* don't recurse */
     }
 
     DPRINTF(1, (stderr, "trying to add file \"%s\"\n", path));
@@ -622,83 +617,57 @@ static int add_file(int percent, register const char *file, const char *dir,
 #ifdef _WIN32
             (!isdir) &&
 #endif
-            ((fd = open(path, O_RDONLY | O_BINARY)) < 0)) ||
+            ((fd = open4read(path)) < 0)) ||
         !path_is_absolute(path))
     {
-        debugprint("sarahhhhh fd=%d path=<%s> dir=<%s> file=<%s> percent=%d\n",
+        debugprint("check file fd=%d path=<%s> dir=<%s> file=<%s> percent=%d\n",
             fd, path, dir, file, percent);
-        found = FALSE;
-        if (dir == NULL && (strchr(file, '/') == NULL))
-        {
-            if (((sp = strrchr(file, '-')) != NULL) && (strcmp(sp, "-o") == 0))
-            {
-                /* BSD-style '-o' offensive file suffix */
-                *sp = '\0';
-                found =
-                    (add_file(percent, file, LOCOFFDIR, head, tail, parent)) ||
-                    add_file(percent, file, OFFDIR, head, tail, parent);
-                /* put the suffix back in for better identification later */
-                *sp = '-';
-            }
-            else if (All_forts)
-                found =
-                    (add_file(percent, file, LOCFORTDIR, head, tail, parent) ||
-                        add_file(
-                            percent, file, LOCOFFDIR, head, tail, parent) ||
-                        add_file(percent, file, FORTDIR, head, tail, parent) ||
-                        add_file(percent, file, OFFDIR, head, tail, parent));
-            else if (Offend)
-                found =
-                    (add_file(percent, file, LOCOFFDIR, head, tail, parent) ||
-                        add_file(percent, file, OFFDIR, head, tail, parent));
-            else
-                found =
-                    (add_file(percent, file, LOCFORTDIR, head, tail, parent) ||
-                        add_file(percent, file, FORTDIR, head, tail, parent));
-        }
-        if (!found && parent == NULL && dir == NULL)
+        bool found = false;
+        if (!found && !parent && !dir)
         { /* don't display an error when trying language specific files */
             if (env_lang)
             {
-                char *lang;
                 char llang[512];
                 char langdir[1024];
                 int ret = 0;
-                char *p;
 
                 strncpy(llang, env_lang, sizeof(llang));
                 llang[sizeof(llang) - 1] = '\0';
-                lang = llang;
+                char *lang = llang;
 
                 /* the language string can be like "es:fr_BE:ga" */
                 while (!ret && lang && (*lang))
                 {
-                    p = strchr(lang, ':');
+                    char *p = strchr(lang, ':');
                     if (p)
+                    {
                         *p++ = '\0';
+                    }
                     snprintf(langdir, sizeof(langdir), "%s/%s", FORTDIR, lang);
 
                     if (strncmp(path, lang, 2) == 0)
+                    {
                         ret = 1;
+                    }
                     else if (strncmp(path, langdir, strlen(FORTDIR) + 3) == 0)
+                    {
                         ret = 1;
+                    }
                     lang = p;
                 }
                 if (!ret)
                 {
-                    debugprint("moshe\n");
                     perror(path);
                 }
             }
             else
             {
-                debugprint("abe\n");
                 perror(path);
             }
         }
 
-        if (was_malloc)
-            free(path);
+        free(path);
+        path = NULL;
         return found;
     }
 
@@ -708,19 +677,19 @@ static int add_file(int percent, register const char *file, const char *dir,
     fp->fd = fd;
     fp->percent = percent;
 
-    fp->name = do_malloc(strlen(file) + (size_t)1);
-    strncpy(fp->name, file, strlen(file) + (size_t)1);
-
-    fp->path = do_malloc(strlen(path) + (size_t)1);
-    strncpy(fp->path, path, strlen(path) + 1UL);
+    fp->name = strdup(file);
+    fp->path = strdup(path);
 
     // FIXME
-    fp->utf8_charset = FALSE;
-    testpath = do_malloc(strlen(path) + 4UL);
-    sprintf(testpath, "%s.u8", path);
+    fp->utf8_charset = false;
+    const size_t do_len = (strlen(path) + 5);
+    char *testpath = do_malloc(do_len + 1);
+    snprintf(testpath, do_len, "%s.u8", path);
     //    fprintf(stderr, "State mal: %s\n", testpath);
     if (stat(testpath, &statbuf) == 0)
-        fp->utf8_charset = TRUE;
+    {
+        fp->utf8_charset = true;
+    }
 
     free(testpath);
     testpath = NULL;
@@ -730,19 +699,23 @@ static int add_file(int percent, register const char *file, const char *dir,
 
     if ((isdir && !add_dir(fp)) || (!isdir && !is_fortfile(path, &fp->datfile)))
     {
-        if (parent == NULL)
+        if (!parent)
+        {
             fprintf(
                 stderr, "fortune:%s not a fortune file or directory\n", path);
-        if (was_malloc)
-            free(path);
-        do_free(fp->datfile);
-        do_free(fp->posfile);
-        do_free(fp->name);
-        do_free(fp->path);
+        }
+        free(path);
+        path = NULL;
+        free(fp->datfile);
+        free(fp->posfile);
+        free(fp->name);
+        free(fp->path);
         if (fp->fd >= 0)
+        {
             close(fp->fd);
+        }
         free(fp);
-        return FALSE;
+        return false;
     }
 
     /* This is a hack to come around another hack - add_dir returns success
@@ -750,21 +723,25 @@ static int add_file(int percent, register const char *file, const char *dir,
      * empty directory... */
     if (isdir && fp->num_children == 0)
     {
-        if (was_malloc)
-            free(path);
-        do_free(fp->datfile);
-        do_free(fp->posfile);
-        do_free(fp->name);
-        do_free(fp->path);
+        free(path);
+        path = NULL;
+        free(fp->datfile);
+        free(fp->posfile);
+        free(fp->name);
+        free(fp->path);
         if (fp->fd >= 0)
+        {
             close(fp->fd);
+        }
         free(fp);
-        return TRUE;
+        return true;
     }
     /* End hack. */
 
-    if (*head == NULL)
+    if (!(*head))
+    {
         *head = *tail = fp;
+    }
     else if (fp->percent == NO_PROB)
     {
         (*tail)->next = fp;
@@ -778,41 +755,35 @@ static int add_file(int percent, register const char *file, const char *dir,
         *head = fp;
     }
 
-    if (was_malloc)
-    {
-        free(path);
-        path = NULL;
-    }
+    free(path);
+    path = NULL;
 
-    return TRUE;
+    return true;
 }
 
 static int names_compare(const void *a, const void *b)
 {
-    return strcmp(*(const char **)a, *(const char **)b);
+    return strcmp(*(const char *const *)a, *(const char *const *)b);
 }
 /*
  * add_dir:
  *      Add the contents of an entire directory.
  */
-int add_dir(register FILEDESC *fp)
+static int add_dir(FILEDESC *const fp)
 {
-    register DIR *dir;
-    register struct dirent *dirent;
-    auto FILEDESC *tailp;
-    auto char *name;
+    DIR *dir;
+    struct dirent *dirent;
     char **names;
     size_t i, count_names, max_count_names;
 
     close(fp->fd);
     fp->fd = -1;
-    if ((dir = opendir(fp->path)) == NULL)
+    if (!(dir = opendir(fp->path)))
     {
-        debugprint("yonah\n");
         perror(fp->path);
-        return FALSE;
+        return false;
     }
-    tailp = NULL;
+    FILEDESC *tailp = NULL;
     DPRINTF(1, (stderr, "adding dir \"%s\"\n", fp->path));
     fp->num_children = 0;
     max_count_names = 200;
@@ -820,22 +791,22 @@ int add_dir(register FILEDESC *fp)
     names = malloc(sizeof(names[0]) * max_count_names);
     if (!names)
     {
-        debugprint("zach\n");
         perror("Out of RAM!");
         exit(-1);
     }
-    while ((dirent = readdir(dir)) != NULL)
+    while ((dirent = readdir(dir)))
     {
         if (dirent->d_name[0] == 0)
+        {
             continue;
-        name = strdup(dirent->d_name);
+        }
+        char *name = strdup(dirent->d_name);
         if (count_names == max_count_names)
         {
             max_count_names += 200;
             names = realloc(names, sizeof(names[0]) * max_count_names);
             if (!names)
             {
-                debugprint("rebecca\n");
                 perror("Out of RAM!");
                 exit(-1);
             }
@@ -865,13 +836,13 @@ int add_dir(register FILEDESC *fp)
         if (strcmp(LOCFORTDIR, fp->path) == 0 ||
             strcmp(LOCOFFDIR, fp->path) == 0)
         {
-            return TRUE;
+            return true;
         }
         fprintf(
             stderr, "fortune: %s: No fortune files in directory.\n", fp->path);
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 /*
@@ -909,10 +880,10 @@ static int top_level_LOCFORTDIR(void)
     return (top_level__add_file(LOCFORTDIR) | cond_top_level__LOCFORTDIR());
 }
 
-static int form_file_list(register char **files, register int file_cnt)
+static int form_file_list(char **files, int file_cnt)
 {
-    register int i, percent;
-    register char *sp;
+    int i, percent;
+    char *sp;
     char langdir[1024];
     char fullpathname[512], locpathname[512];
 
@@ -946,7 +917,9 @@ static int form_file_list(register char **files, register int file_cnt)
                 {
                     p = strchr(lang, ':');
                     if (p)
+                    {
                         *p++ = '\0';
+                    }
 
                     /* first try full locale */
                     ret = add_file(
@@ -965,7 +938,9 @@ static int form_file_list(register char **files, register int file_cnt)
 
                     /* if we have found one we have finished */
                     if (ret)
+                    {
                         return ret;
+                    }
                     lang = p;
                 }
                 /* default */
@@ -983,23 +958,45 @@ static int form_file_list(register char **files, register int file_cnt)
     {
         percent = NO_PROB;
         if (!isdigit(files[i][0]))
+        {
             sp = files[i];
+        }
         else
         {
+            const int MAX_PERCENT = 100;
+            bool percent_has_overflowed = false;
             percent = 0;
             for (sp = files[i]; isdigit(*sp); sp++)
+            {
                 percent = percent * 10 + *sp - '0';
-            if (percent > 100)
+                percent_has_overflowed = (percent > MAX_PERCENT);
+                if (percent_has_overflowed)
+                {
+                    break;
+                }
+            }
+            if (percent_has_overflowed || (percent > 100))
             {
                 fprintf(stderr, "percentages must be <= 100\n");
-                ErrorMessage = TRUE;
-                return FALSE;
+                fprintf(stderr,
+                    "Overflow percentage detected at argument \"%s\"!\n",
+                    files[i]);
+                ErrorMessage = true;
+                return false;
+            }
+            if (percent < 0)
+            {
+                fprintf(stderr,
+                    "Overflow percentage detected at argument \"%s\"!\n",
+                    files[i]);
+                ErrorMessage = true;
+                return false;
             }
             if (*sp == '.')
             {
-                fprintf(stderr, "percentages must be integers\n");
-                ErrorMessage = TRUE;
-                return FALSE;
+                fprintf(stderr, "%s", "percentages must be integers\n");
+                ErrorMessage = true;
+                return false;
             }
             /*
              * If the number isn't followed by a '%', then
@@ -1015,17 +1012,30 @@ static int form_file_list(register char **files, register int file_cnt)
             {
                 if (++i >= file_cnt)
                 {
-                    fprintf(stderr, "percentages must precede files\n");
-                    ErrorMessage = TRUE;
-                    return FALSE;
+                    fprintf(stderr, "%s", "percentages must precede files\n");
+                    ErrorMessage = true;
+                    return false;
                 }
                 sp = files[i];
             }
         }
+
+        /* BSD-style '-o' offensive file suffix */
+        bool offensive = false;
+        const size_t sp_len = strlen(sp);
+        if (sp_len >= 3 && sp[sp_len - 2] == '-' && sp[sp_len - 1] == 'o')
+        {
+            sp[sp_len - 2] = '\0';
+            offensive = true;
+        }
+
+        const char* fulldir = offensive ? OFFDIR : FORTDIR;
+        const char* locdir = offensive ? LOCOFFDIR : LOCFORTDIR;
+
         if (strcmp(sp, "all") == 0)
         {
-            snprintf(fullpathname, sizeof(fullpathname), "%s", FORTDIR);
-            snprintf(locpathname, sizeof(locpathname), "%s", LOCFORTDIR);
+            snprintf(fullpathname, sizeof(fullpathname), "%s", fulldir);
+            snprintf(locpathname, sizeof(locpathname), "%s", locdir);
         }
         /* if it isn't an absolute path or relative to . or ..
            make it an absolute path relative to FORTDIR */
@@ -1035,9 +1045,9 @@ static int form_file_list(register char **files, register int file_cnt)
                 strncmp(sp, "../", 3) != 0)
             {
                 snprintf(
-                    fullpathname, sizeof(fullpathname), "%s/%s", FORTDIR, sp);
+                    fullpathname, sizeof(fullpathname), "%s/%s", fulldir, sp);
                 snprintf(
-                    locpathname, sizeof(locpathname), "%s/%s", LOCFORTDIR, sp);
+                    locpathname, sizeof(locpathname), "%s/%s", locdir, sp);
             }
             else
             {
@@ -1048,25 +1058,25 @@ static int form_file_list(register char **files, register int file_cnt)
 
         if (env_lang)
         {
-            char *lang;
             char llang[512];
             int ret = 0;
-            char *p;
 
             strncpy(llang, env_lang, sizeof(llang));
             llang[sizeof(llang) - 1] = '\0';
-            lang = llang;
+            char *lang = llang;
 
             /* the language string can be like "es:fr_BE:ga" */
             while (!ret && lang && (*lang))
             {
-                p = strchr(lang, ':');
+                char *p = strchr(lang, ':');
                 if (p)
+                {
                     *p++ = '\0';
+                }
 
                 /* first try full locale */
                 snprintf(
-                    langdir, sizeof(langdir), "%s/%s/%s", FORTDIR, lang, sp);
+                    langdir, sizeof(langdir), "%s/%s/%s", fulldir, lang, sp);
                 ret = add_file(
                     percent, langdir, NULL, &File_list, &File_tail, NULL);
 
@@ -1078,7 +1088,7 @@ static int form_file_list(register char **files, register int file_cnt)
                     strncpy(ll, lang, 2);
                     ll[2] = '\0';
                     snprintf(
-                        langdir, sizeof(langdir), "%s/%s/%s", FORTDIR, ll, sp);
+                        langdir, sizeof(langdir), "%s/%s/%s", fulldir, ll, sp);
                     ret = add_file(
                         percent, langdir, NULL, &File_list, &File_tail, NULL);
                 }
@@ -1087,15 +1097,29 @@ static int form_file_list(register char **files, register int file_cnt)
             }
             /* default */
             if (!ret)
+            {
                 ret = add_file(
                     percent, fullpathname, NULL, &File_list, &File_tail, NULL);
+            }
             if (!ret &&
                 strncmp(fullpathname, locpathname, sizeof(fullpathname)))
+            {
                 ret = add_file(
                     percent, locpathname, NULL, &File_list, &File_tail, NULL);
-
+            }
+            if (strncmp(fullpathname, locpathname, sizeof(fullpathname)) &&
+                strcmp(sp, "all") == 0)
+            {
+                add_file(
+                    percent, locpathname, NULL, &File_list, &File_tail, NULL);
+            }
             if (!ret)
             {
+                if (offensive)
+                {
+                    // restore -o suffix
+                    sp[sp_len - 2] = '-';
+                }
                 snprintf(locpathname, sizeof(locpathname), "%s/%s",
                     getenv("PWD"), sp);
 
@@ -1104,20 +1128,16 @@ static int form_file_list(register char **files, register int file_cnt)
             }
             if (!ret)
             {
-                return FALSE;
-            }
-            if (strncmp(fullpathname, locpathname, sizeof(fullpathname)) &&
-                strcmp(sp, "all") == 0)
-            {
-                add_file(
-                    percent, locpathname, NULL, &File_list, &File_tail, NULL);
+                return false;
             }
         }
         else if (!add_file(
                      percent, fullpathname, NULL, &File_list, &File_tail, NULL))
-            return FALSE;
+        {
+            return false;
+        }
     }
-    return TRUE;
+    return true;
 }
 
 /*
@@ -1125,16 +1145,13 @@ static int form_file_list(register char **files, register int file_cnt)
  */
 static void getargs(int argc, char **argv)
 {
-    register int ignore_case;
-
-#ifndef NO_REGEX
-    register char *pat = NULL;
+#ifdef WITH_REGEX
+    bool ignore_case = false;
+    char *pat = NULL;
+#endif
 
-#endif /* NO_REGEX */
     int ch;
 
-    ignore_case = FALSE;
-
 #ifdef DEBUG
 #define DEBUG_GETOPT "D"
 #else
@@ -1148,11 +1165,12 @@ static void getargs(int argc, char **argv)
 #endif
 
     while ((ch = getopt(argc, argv,
-                "ac" DEBUG_GETOPT "efilm:n:" OFFENSIVE_GETOPT "suvw")) != EOF)
+                "ac" DEBUG_GETOPT "efhilm:n:" OFFENSIVE_GETOPT "suvw")) != EOF)
+    {
         switch (ch)
         {
         case 'a': /* any fortune */
-            All_forts = TRUE;
+            All_forts = true;
             break;
 #ifdef DEBUG
         case 'D':
@@ -1160,77 +1178,88 @@ static void getargs(int argc, char **argv)
             break;
 #endif /* DEBUG */
         case 'e':
-            Equal_probs = TRUE; /* scatter un-allocted prob equally */
+            Equal_probs = true; /* scatter un-allocted prob equally */
             break;
         case 'f': /* find fortune files */
-            Find_files = TRUE;
+            Find_files = true;
             break;
         case 'l': /* long ones only */
-            Long_only = TRUE;
-            Short_only = FALSE;
+            Long_only = true;
+            Short_only = false;
             break;
         case 'n':
             SLEN = atoi(optarg);
             break;
 #ifndef NO_OFFENSIVE
         case 'o': /* offensive ones only */
-            Offend = TRUE;
+            Offend = true;
             break;
 #endif
         case 's': /* short ones only */
-            Short_only = TRUE;
-            Long_only = FALSE;
+            Short_only = true;
+            Long_only = false;
             break;
         case 'w': /* give time to read */
-            Wait = TRUE;
+            Wait = true;
             break;
 #ifdef NO_REGEX
         case 'i': /* case-insensitive match */
         case 'm': /* dump out the fortunes */
-            (void)fprintf(stderr,
-                "fortune: can't match fortunes on this system (Sorry)\n");
+            (void)fprintf(stderr, "%s",
+                "fortune: can't match fortunes on this system "
+                "(Sorry)\n");
             exit(0);
 #else             /* NO_REGEX */
         case 'm': /* dump out the fortunes */
-            Match = TRUE;
+            Match = true;
             pat = optarg;
             break;
         case 'i': /* case-insensitive match */
-            ignore_case++;
+            ignore_case = true;
             break;
 #endif            /* NO_REGEX */
         case 'u': /* Don't recode the fortune */
-            No_recode = TRUE;
+            No_recode = true;
             break;
         case 'v':
             (void)printf("%s\n", program_version());
             exit(0);
         case 'c':
-            Show_filename = TRUE;
+            Show_filename = true;
             break;
+        case 'h':
         case '?':
         default:
             usage();
         }
+    }
     argc -= optind;
     argv += optind;
 
     if (!form_file_list(argv, argc))
     {
         if (!ErrorMessage)
-            fprintf(stderr, "No fortunes found\n");
+        {
+            fprintf(stderr, "%s", "No fortunes found\n");
+        }
         exit(1); /* errors printed through form_file_list() */
     }
 #ifdef DEBUG
-/*      if (Debug >= 1)
- * print_list(File_list, 0); */
-#endif /* DEBUG */
+#if 0
+      if (Debug >= 1)
+ print_list(File_list, 0); /* Causes crash with new %% code */
+
+#endif
+#endif
+
 /* If (Find_files) print_list() moved to main */
-#ifndef NO_REGEX
-    if (pat != NULL)
+#ifdef WITH_REGEX
+    if (pat)
     {
         if (ignore_case)
+        {
             pat = conv_pat(pat);
+        }
         if (BAD_COMP(RE_COMP(pat)))
         {
             fprintf(stderr, "bad pattern: %s\n", pat);
@@ -1241,7 +1270,7 @@ static void getargs(int argc, char **argv)
             free(pat);
         }
     }
-#endif /* NO_REGEX */
+#endif
 }
 
 /*
@@ -1250,27 +1279,30 @@ static void getargs(int argc, char **argv)
  */
 static void init_prob(void)
 {
-    register FILEDESC *fp, *last;
-    register int percent, num_noprob, frac;
+    FILEDESC *fp;
+    int percent = 0, num_noprob = 0, frac;
 
     /*
      * Distribute the residual probability (if any) across all
      * files with unspecified probability (i.e., probability of 0)
      * (if any).
      */
-
-    percent = 0;
-    num_noprob = 0;
-    last = NULL;
-    for (fp = File_tail; fp != NULL; fp = fp->prev)
+    FILEDESC *last = NULL;
+    for (fp = File_tail; fp; fp = fp->prev)
+    {
         if (fp->percent == NO_PROB)
         {
             num_noprob++;
             if (Equal_probs)
+            {
                 last = fp;
+            }
         }
         else
+        {
             percent += fp->percent;
+        }
+    }
     DPRINTF(1, (stderr, "summing probabilities:%d%% with %d NO_PROB's\n",
                    percent, num_noprob));
     if (percent > 100)
@@ -1281,16 +1313,19 @@ static void init_prob(void)
     else if (percent < 100 && num_noprob == 0)
     {
         fprintf(stderr,
-            "fortune: no place to put residual probability (%d%%)\n", percent);
+            "fortune: no place to put residual probability "
+            "(%d%%)\n",
+            percent);
         exit(1);
     }
     else if (percent == 100 && num_noprob != 0)
     {
-        fprintf(
-            stderr, "fortune: no probability left to put in residual files\n");
+        fprintf(stderr, "fortune: no probability left to put in "
+                        "residual files\n");
         exit(1);
     }
-    Spec_prob = percent; /* this is for -f when % is specified on cmd line */
+    Spec_prob = percent; /* this is for -f when % is specified on
+                            cmd line */
     percent = 100 - percent;
     if (Equal_probs)
     {
@@ -1301,11 +1336,13 @@ static void init_prob(void)
                 frac = percent / num_noprob;
                 DPRINTF(1, (stderr, ", frac = %d%%", frac));
                 for (fp = File_tail; fp != last; fp = fp->prev)
+                {
                     if (fp->percent == NO_PROB)
                     {
                         fp->percent = frac;
                         percent -= frac;
                     }
+                }
             }
             last->percent = percent;
             DPRINTF(1, (stderr, ", residual = %d%%", percent));
@@ -1316,11 +1353,16 @@ static void init_prob(void)
                            percent));
         }
     }
-    DPRINTF(1, (stderr, "\n"));
+    DPRINTF(1, (stderr, "%s", "\n"));
 
 #ifdef DEBUG
-/*      if (Debug >= 1)
- * print_list(File_list, 0); *//* Causes crash with new %% code */
+#if 0
+      if (Debug >= 1)
+    {
+ print_list(File_list, 0); /* Causes crash with new %% code */
+    }
+
+#endif
 #endif
 }
 
@@ -1328,7 +1370,7 @@ static void init_prob(void)
  * zero_tbl:
  *      Zero out the fields we care about in a tbl structure.
  */
-static void zero_tbl(register STRFILE *tp)
+static void zero_tbl(STRFILE *tp)
 {
     tp->str_numstr = 0;
     tp->str_longlen = 0;
@@ -1339,13 +1381,17 @@ static void zero_tbl(register STRFILE *tp)
  * sum_tbl:
  *      Merge the tbl data of t2 into t1.
  */
-static void sum_tbl(register STRFILE *t1, register STRFILE *t2)
+static void sum_tbl(STRFILE *t1, STRFILE *t2)
 {
     t1->str_numstr += t2->str_numstr;
     if (t1->str_longlen < t2->str_longlen)
+    {
         t1->str_longlen = t2->str_longlen;
+    }
     if (t1->str_shortlen > t2->str_shortlen)
+    {
         t1->str_shortlen = t2->str_shortlen;
+    }
 }
 
 /*
@@ -1354,32 +1400,16 @@ static void sum_tbl(register STRFILE *t1, register STRFILE *t2)
  */
 static void get_tbl(FILEDESC *fp)
 {
-    auto int fd;
-    register FILEDESC *child;
+    int fd;
+    FILEDESC *child;
 
     if (fp->read_tbl)
+    {
         return;
-    if (fp->child == NULL)
+    }
+    if (!(fp->child))
     {
-#if 0
-        /* This should not be needed anymore since add_file takes care of
-         * empty directories now (Torsten Landschoff <torsten@debian.org>)
-         */
-
-        /*
-         * Only the local fortune dir and the local offensive dir are
-         * allowed to be empty.  Don't try and fetch their tables if
-         * they have no children (i.e. are empty).
-         *  - Brian Bassett (brianb@debian.org) 1999/07/31
-         */
-        if (strcmp(LOCFORTDIR, fp->path) == 0 || strcmp(LOCOFFDIR, fp->path) == 0)
-        {
-            fp->read_tbl = TRUE;        /* Make it look like we've read it. */
-            return;
-        }
-        /* End */
-#endif
-        if ((fd = open(fp->datfile, O_RDONLY | O_BINARY)) < 0)
+        if ((fd = open4read(fp->datfile)) < 0)
         {
             perror(fp->datfile);
             exit(1);
@@ -1430,36 +1460,40 @@ static void get_tbl(FILEDESC *fp)
     else
     {
         zero_tbl(&fp->tbl);
-        for (child = fp->child; child != NULL; child = child->next)
+        for (child = fp->child; child; child = child->next)
         {
             get_tbl(child);
             sum_tbl(&fp->tbl, &child->tbl);
         }
     }
-    fp->read_tbl = TRUE;
+    fp->read_tbl = true;
 }
 
 /*
  * sum_noprobs:
  *      Sum up all the noprob probabilities, starting with fp.
  */
-static void sum_noprobs(register FILEDESC *fp)
+static void sum_noprobs(FILEDESC *fp)
 {
-    static bool did_noprobs = FALSE;
+    static bool did_noprobs = false;
 
     if (did_noprobs)
+    {
         return;
+    }
     zero_tbl(&Noprob_tbl);
-    while (fp != NULL)
+    while (fp)
     {
         get_tbl(fp);
-        /* This conditional should help us return correct values for -f
-         * when a percentage is specified */
+        /* This conditional should help us return correct values for
+         * -f when a percentage is specified */
         if (fp->percent == NO_PROB)
+        {
             sum_tbl(&Noprob_tbl, &fp->tbl);
+        }
         fp = fp->next;
     }
-    did_noprobs = TRUE;
+    did_noprobs = true;
 }
 
 /*
@@ -1468,16 +1502,18 @@ static void sum_noprobs(register FILEDESC *fp)
  */
 static FILEDESC *pick_child(FILEDESC *parent)
 {
-    register FILEDESC *fp;
-    register int choice;
+    FILEDESC *fp;
+    int choice;
 
     if (Equal_probs)
     {
-        choice = my_random(parent->num_children);
+        choice = (int)my_random((unsigned long)parent->num_children);
         DPRINTF(1, (stderr, "    choice = %d (of %d)\n", choice,
                        parent->num_children));
         for (fp = parent->child; choice--; fp = fp->next)
+        {
             continue;
+        }
         DPRINTF(1, (stderr, "    using %s\n", fp->name));
         return fp;
     }
@@ -1506,8 +1542,7 @@ static FILEDESC *pick_child(FILEDESC *parent)
  */
 static void open_dat(FILEDESC *fp)
 {
-    if (fp->datfd < 0 &&
-        (fp->datfd = open(fp->datfile, O_RDONLY | O_BINARY)) < 0)
+    if (fp->datfd < 0 && (fp->datfd = open4read(fp->datfile)) < 0)
     {
         exit(1);
     }
@@ -1515,8 +1550,8 @@ static void open_dat(FILEDESC *fp)
 
 /*
  * get_pos:
- *      Get the position from the pos file, if there is one.  If not,
- *      return a random number.
+ *      Get the position from the pos file, if there is one.  If
+ * not, return a random number.
  */
 static void get_pos(FILEDESC *fp)
 {
@@ -1526,42 +1561,53 @@ static void get_pos(FILEDESC *fp)
         fp->pos = (int32_t)(my_random(fp->tbl.str_numstr));
     }
     if (++(fp->pos) >= (int32_t)fp->tbl.str_numstr)
+    {
         fp->pos -= fp->tbl.str_numstr;
+    }
     DPRINTF(1, (stderr, "pos for %s is %ld\n", fp->name, fp->pos));
 }
 
 /*
  * get_fort:
- *      Get the fortune data file's seek pointer for the next fortune.
+ *      Get the fortune data file's seek pointer for the next
+ * fortune.
  */
 static void get_fort(void)
 {
-    register FILEDESC *fp;
-    register int choice;
+    FILEDESC *fp;
+    int choice;
 
-    if (File_list->next == NULL || File_list->percent == NO_PROB)
+    if (!File_list->next || File_list->percent == NO_PROB)
+    {
         fp = File_list;
+    }
     else
     {
-        choice = my_random(100);
+        choice = (int)my_random(100);
         DPRINTF(1, (stderr, "choice = %d\n", choice));
         for (fp = File_list; fp->percent != NO_PROB; fp = fp->next)
+        {
             if (choice < fp->percent)
+            {
                 break;
+            }
             else
             {
                 choice -= fp->percent;
                 DPRINTF(1, (stderr, "    skip \"%s\", %d%% (choice = %d)\n",
                                fp->name, fp->percent, choice));
             }
+        }
         DPRINTF(1, (stderr, "using \"%s\", %d%% (choice = %d)\n", fp->name,
                        fp->percent, choice));
     }
     if (fp->percent != NO_PROB)
+    {
         get_tbl(fp);
+    }
     else
     {
-        if (fp->next != NULL)
+        if (fp->next)
         {
             sum_noprobs(fp);
             choice = (int)(my_random(Noprob_tbl.str_numstr));
@@ -1581,12 +1627,12 @@ static void get_fort(void)
     }
     if (fp->tbl.str_numstr == 0)
     {
-        fprintf(stderr, "fortune: no fortune found\n");
+        fprintf(stderr, "%s", "fortune: no fortune found\n");
         exit(1);
     }
-    if (fp->child != NULL)
+    if (fp->child)
     {
-        DPRINTF(1, (stderr, "picking child\n"));
+        DPRINTF(1, (stderr, "%s", "picking child\n"));
         fp = pick_child(fp);
     }
     Fortfile = fp;
@@ -1609,30 +1655,31 @@ static void get_fort(void)
  */
 static void open_fp(FILEDESC *fp)
 {
-    if (fp->inf == NULL && (fp->inf = fdopen(fp->fd, "r")) == NULL)
+    if (!fp->inf && !(fp->inf = fdopen(fp->fd, "r")))
     {
         perror(fp->path);
         exit(1);
     }
 }
 
-#ifndef NO_REGEX
+#ifdef WITH_REGEX
 /*
  * maxlen_in_list
  *      Return the maximum fortune len in the file list.
  */
 static int maxlen_in_list(FILEDESC *list)
 {
-    register FILEDESC *fp;
-    register int len, maxlen;
+    FILEDESC *fp;
+    int len, maxlen = 0;
 
-    maxlen = 0;
-    for (fp = list; fp != NULL; fp = fp->next)
+    for (fp = list; fp; fp = fp->next)
     {
-        if (fp->child != NULL)
+        if (fp->child)
         {
             if ((len = maxlen_in_list(fp->child)) > maxlen)
+            {
                 maxlen = len;
+            }
         }
         else
         {
@@ -1650,27 +1697,27 @@ static int maxlen_in_list(FILEDESC *list)
  * matches_in_list
  *      Print out the matches from the files in the list.
  */
-static void matches_in_list(FILEDESC *list)
+static void matches_in_list(FILEDESC *list, bool *const Found_one_ptr)
 {
     unsigned char *sp;
     unsigned char *p; /* -allover */
     unsigned char ch; /* -allover */
-    register FILEDESC *fp;
+    FILEDESC *fp;
     int in_file, nchar;
     char *output;
 
-    for (fp = list; fp != NULL; fp = fp->next)
+    for (fp = list; fp; fp = fp->next)
     {
-        if (fp->child != NULL)
+        if (fp->child)
         {
-            matches_in_list(fp->child);
+            matches_in_list(fp->child, Found_one_ptr);
             continue;
         }
         DPRINTF(1, (stderr, "searching in %s\n", fp->path));
         open_fp(fp);
         sp = Fortbuf;
-        in_file = FALSE;
-        while (fgets((char *)sp, Fort_len, fp->inf) != NULL)
+        in_file = false;
+        while (fgets((char *)sp, Fort_len, fp->inf))
         {
             if (!STR_ENDSTRING(sp, fp->tbl))
             {
@@ -1683,11 +1730,7 @@ static void matches_in_list(FILEDESC *list)
 
                 if (fp->utf8_charset && (!No_recode))
                 {
-#ifdef WITH_RECODE
-                    output = recode_string(request, (const char *)Fortbuf);
-#else
-                    output = strdup(Fortbuf);
-#endif
+                    output = my_recode_string((const char *)Fortbuf);
                 }
                 else
                 {
@@ -1700,9 +1743,13 @@ static void matches_in_list(FILEDESC *list)
                     for (p = (unsigned char *)output; (ch = *p); ++p)
                     {
                         if (isupper(ch) && isascii(ch))
+                        {
                             *p = 'A' + (ch - 'A' + 13) % 26;
+                        }
                         else if (islower(ch) && isascii(ch))
+                        {
                             *p = 'a' + (ch - 'a' + 13) % 26;
+                        }
                     }
                 }
 
@@ -1714,15 +1761,18 @@ static void matches_in_list(FILEDESC *list)
                     {
                         fprintf(
                             stderr, "(%s)\n%c\n", fp->name, fp->tbl.str_delim);
-                        Found_one = TRUE;
-                        in_file = TRUE;
+                        (*Found_one_ptr) = true;
+                        in_file = true;
                     }
                     fputs(output, stdout);
                     printf("%c\n", fp->tbl.str_delim);
                 }
 
                 if (fp->utf8_charset && (!No_recode))
+                {
                     free(output);
+                    output = NULL;
+                }
 
                 sp = Fortbuf;
             }
@@ -1732,32 +1782,35 @@ static void matches_in_list(FILEDESC *list)
 
 /*
  * find_matches:
- *      Find all the fortunes which match the pattern we've been given.
+ *      Find all the fortunes which match the pattern we've been
+ * given.
  */
-static int find_matches(void)
+static bool find_matches(void)
 {
     Fort_len = maxlen_in_list(File_list);
     DPRINTF(2, (stderr, "Maximum length is %d\n", Fort_len));
     /* extra length, "%\n" is appended */
     Fortbuf = do_malloc((unsigned int)Fort_len + 10);
 
-    Found_one = FALSE;
-    matches_in_list(File_list);
+    bool Found_one = false;
+    matches_in_list(File_list, &Found_one);
     return Found_one;
     /* NOTREACHED */
 }
-#endif /* NO_REGEX */
+#endif
 
 static void display(FILEDESC *fp)
 {
-    register char *p, ch;
+    char *p, ch;
     unsigned char line[BUFSIZ];
 
     open_fp(fp);
-    fseek(fp->inf, (long)Seekpts[0], 0);
+    fseek(fp->inf, (long)Seekpts[0], SEEK_SET);
     if (Show_filename)
+    {
         printf("(%s)\n%%\n", fp->name);
-    for (Fort_len = 0; fgets((char *)line, sizeof line, fp->inf) != NULL &&
+    }
+    for (Fort_len = 0; fgets((char *)line, sizeof line, fp->inf) &&
                        !STR_ENDSTRING(line, fp->tbl);
          Fort_len++)
     {
@@ -1766,19 +1819,18 @@ static void display(FILEDESC *fp)
             for (p = (char *)line; (ch = *p); ++p)
             {
                 if (isupper(ch) && isascii(ch))
+                {
                     *p = 'A' + (ch - 'A' + 13) % 26;
+                }
                 else if (islower(ch) && isascii(ch))
+                {
                     *p = 'a' + (ch - 'a' + 13) % 26;
+                }
             }
         }
         if (fp->utf8_charset && (!No_recode))
         {
-            char *output;
-#ifdef WITH_RECODE
-            output = recode_string(request, (const char *)line);
-#else
-            output = strdup(line);
-#endif
+            char *output = my_recode_string((const char *)line);
             fputs(output, stdout);
             free(output);
         }
@@ -1794,35 +1846,39 @@ static void display(FILEDESC *fp)
  */
 static int fortlen(void)
 {
-    register int nchar;
+    int nchar;
     char line[BUFSIZ];
 
     if (!(Fortfile->tbl.str_flags & (STR_RANDOM | STR_ORDERED)))
+    {
         nchar = (Seekpts[1] - Seekpts[0]) - 2; /* for %^J delimiter */
+    }
     else
     {
         open_fp(Fortfile);
-        fseek(Fortfile->inf, (long)Seekpts[0], 0);
+        fseek(Fortfile->inf, (long)Seekpts[0], SEEK_SET);
         nchar = 0;
-        while (fgets(line, sizeof line, Fortfile->inf) != NULL &&
+        while (fgets(line, sizeof line, Fortfile->inf) &&
                !STR_ENDSTRING(line, Fortfile->tbl))
+        {
             nchar += strlen(line);
+        }
     }
     Fort_len = nchar;
     return nchar;
 }
 
-static int mymax(register int i, register int j) { return (i >= j ? i : j); }
+static int mymax(int i, int j) { return (i >= j ? i : j); }
 
 static void free_desc(FILEDESC *ptr)
 {
     while (ptr)
     {
         free_desc(ptr->child);
-        do_free(ptr->datfile);
-        do_free(ptr->posfile);
-        do_free(ptr->name);
-        do_free(ptr->path);
+        free(ptr->datfile);
+        free(ptr->posfile);
+        free(ptr->name);
+        free(ptr->path);
         if (ptr->inf)
         {
             fclose(ptr->inf);
@@ -1834,18 +1890,26 @@ static void free_desc(FILEDESC *ptr)
     }
 }
 
-int main(int ac, char *av[])
+int main(int argc, char *argv[])
 {
+#ifdef WITH_RECODE
     const char *ctype;
-    char *crequest;
+#endif
+
     int exit_code = 0;
     env_lang = getenv("LC_ALL");
     if (!env_lang)
+    {
         env_lang = getenv("LC_MESSAGES");
+    }
     if (!env_lang)
+    {
         env_lang = getenv("LANGUAGE");
+    }
     if (!env_lang)
+    {
         env_lang = getenv("LANG");
+    }
 #ifdef _WIN32
     if (!env_lang)
     {
@@ -1853,16 +1917,15 @@ int main(int ac, char *av[])
     }
 #endif
 
-#ifndef DONT_CALL_GETARGS
-    getargs(ac, av);
-#endif
-
+    getargs(argc, argv);
 #ifdef WITH_RECODE
     outer = recode_new_outer(true);
     request = recode_new_request(outer);
 #endif
 
     setlocale(LC_ALL, "");
+
+#ifdef WITH_RECODE
 #ifdef _WIN32
     ctype = "C";
 #else
@@ -1876,33 +1939,35 @@ int main(int ac, char *av[])
         ctype = "ISO-8859-1";
     }
 #endif
-
-#ifdef WITH_RECODE
-    crequest = malloc(strlen(ctype) + 7 + 1);
-    sprintf(crequest, "UTF-8..%s", ctype);
+    const size_t do_len = strlen(ctype) + (7 + 1 + GCC_SNPRINTF_MARGIN);
+    char *crequest = do_malloc(do_len + 1);
+    snprintf(crequest, do_len, "UTF-8..%s", ctype);
     recode_scan_request(request, crequest);
     free(crequest);
 #endif
 
-#ifndef NO_REGEX
+#ifdef WITH_REGEX
     if (Match)
     {
-        exit_code = (find_matches() != 0);
+        exit_code = find_matches();
         regfree(&Re_pat);
         goto cleanup;
     }
 #endif
+
     init_prob();
     if (Find_files)
     {
         sum_noprobs(File_list);
         if (Equal_probs)
+        {
             calc_equal_probs();
+        }
         print_list(File_list, 0);
     }
     else
     {
-        srandom((unsigned int)(time((time_t *)NULL) + getpid()));
+        call_srandom();
         do
         {
             get_fort();
@@ -1917,7 +1982,10 @@ int main(int ac, char *av[])
             sleep((unsigned int)mymax(Fort_len / CPERS, MINW));
         }
     }
+#ifdef WITH_REGEX
 cleanup:
+#endif
+
 #ifdef WITH_RECODE
     recode_delete_request(request);
     recode_delete_outer(outer);
@@ -1927,5 +1995,4 @@ cleanup:
     free_desc(File_list);
     free(Fortbuf);
     exit(exit_code);
-    /* NOTREACHED */
 }