Makefile | 8 +- datfiles/Makefile | 4 - datfiles/off/Makefile | 2 - datfiles/riddles | 3 - fortune/fortune.c | 194 +++++++++++++++++++++++++++++++----------------- util/randstr.c | 79 +++++++++++++++++++- 6 files changed, 203 insertions(+), 87 deletions(-) diff --git a/Makefile b/Makefile index 89e1385..4048d7b 100644 --- a/Makefile +++ b/Makefile @@ -62,11 +62,9 @@ REGEXDEFS=-DHAVE_REGEX_H -DBSD_REGEX -DHAVE_STDBOOL # REGEXLIBS= -RECODELIBS=-lrecode - DEFINES=-DFORTDIR="\"$(COOKIEDIR)\"" -DOFFDIR="\"$(OCOOKIEDIR)\"" -DLOCFORTDIR="\"$(LOCALDIR)\"" -DLOCOFFDIR="\"$(LOCALODIR)\"" -CFLAGS=-O2 $(DEFINES) -Wall -fomit-frame-pointer -pipe -fsigned-char -LDFLAGS=-s +CFLAGS=$(RPM_OPT_FLAGS) $(DEFINES) -Wall -fomit-frame-pointer -pipe -fsigned-char +LDFLAGS= # The above flags are used by default; the debug flags are used when make # is called with a debug target, such as 'make debug' @@ -103,7 +101,7 @@ debug: fortune-debug util-debug cookies-z fortune-bin: cd fortune && $(MAKE) CC='$(CC)' \ CFLAGS='$(CFLAGS) $(REGEXDEFS) -I../util' \ - LDFLAGS='$(LDFLAGS)' LIBS='$(REGEXLIBS) $(RECODELIBS)' + LDFLAGS='$(LDFLAGS)' LIBS='$(REGEXLIBS)' fortune-debug: cd fortune && $(MAKE) CC='$(CC)' \ diff --git a/datfiles/Makefile b/datfiles/Makefile index 1fb2b58..70a6e9e 100644 --- a/datfiles/Makefile +++ b/datfiles/Makefile @@ -46,9 +46,7 @@ cookies-stamp: if [ ! -f $$i.old ] ; then \ cp $$i $$i.old; \ fi; \ - recode latin1..u8 $$i ; \ $(STRFILE) $$i ; \ - ln -s $$i $$i.u8 || exit $? ; \ done touch cookies-stamp @@ -58,12 +56,10 @@ install: cookies-stamp if [ $(WEB) = 1 ] ; then cd html && $(MAKE) install ; fi for i in $(COOKIES) ; do \ install -m 0644 $$i $$i.dat $(COOKIEDIR) || exit $? ; \ - cp -d $$i.u8 $(COOKIEDIR) ; \ done clean: rm -f cookies-stamp *.dat - rm -f *.u8 cd off && $(MAKE) clean cd html && $(MAKE) clean for i in $(COOKIES) ; do \ diff --git a/datfiles/off/Makefile b/datfiles/off/Makefile index 3a78738..896af7d 100644 --- a/datfiles/off/Makefile +++ b/datfiles/off/Makefile @@ -30,7 +30,6 @@ recoded-stamp: if [ ! -f unrotated/$$i.old ]; then \ cp unrotated/$$i unrotated/$$i.old ; \ fi; \ - recode latin1..u8 unrotated/$$i; \ done touch recoded-stamp @@ -38,7 +37,6 @@ install: install -m 0755 -d $(OCOOKIEDIR) for i in $(OCOOKIES) ; \ do install -m 0644 $$i $$i.dat $(OCOOKIEDIR) || exit $$? ; \ - cp -d $$i.u8 $(OCOOKIEDIR) ; \ done clean: diff --git a/datfiles/riddles b/datfiles/riddles index 7afbae5..54cabf3 100644 --- a/datfiles/riddles +++ b/datfiles/riddles @@ -419,9 +419,6 @@ A: Nothing. Q: What's a light-year? A: One-third less calories than a regular year. % -Q: What's a WASP's idea of open-mindedness? -A: Dating a Canadian. -% Q: What's buried in Grant's tomb? A: A corpse. % diff --git a/fortune/fortune.c b/fortune/fortune.c index 05520fa..80717ee 100644 --- a/fortune/fortune.c +++ b/fortune/fortune.c @@ -140,8 +140,7 @@ typedef enum #include #include #include -#include - +#include /* This makes GNU libc to prototype the BSD regex functions */ #ifdef BSD_REGEX @@ -189,7 +188,6 @@ typedef struct fd char *datfile, *posfile; bool read_tbl; bool was_pos_file; - bool utf8_charset; STRFILE tbl; int num_children; struct fd *child, *parent; @@ -252,8 +250,8 @@ regex_t Re_pat; #endif /* BSD_REGEX */ -RECODE_REQUEST request; -RECODE_OUTER outer; +iconv_t cd = NULL; +char *Codeset = NULL; int add_dir(register FILEDESC *); @@ -287,6 +285,57 @@ void usage(void) /* + * fortune_iconv: + * Translate text from UTF-8 to current CODESET (LC_CTYPE). + * Thanx to Alexander Bokovoy for this code. + */ +int fortune_iconv(iconv_t _cd, char *inbuf, int inlen, char *outbuf, int outlen) +{ + char *outptr; + size_t n; + int needed_from; + + if (_cd && _cd == (iconv_t) -1) { + memmove(outbuf, inbuf, inlen); + return 0; + } + + outptr = outbuf; + while (inlen > 0) { + n = iconv (_cd, (char **) &inbuf, &inlen, &outptr, &outlen); + + if(inlen == 0) break; + + if (n != (size_t) - 1) { + n = iconv (_cd, NULL, NULL, &outptr, &outlen); + + break; + } + + if (errno != E2BIG) { + switch (errno) { + case EILSEQ: + case EINVAL: + needed_from = ((__gconv_t) _cd)->__steps->__min_needed_from; + outptr[0] = '?'; + outptr++; + outlen--; + inbuf += needed_from; + inlen -= needed_from; + break; + default: + return -1; + } + } else { + /* FIXME: no space left in output buffer */ + break; + } + } + outptr[0] = 0; + return 0; +} + +/* * calc_equal_probs: * Set the global values for number of files/children, to be used * in printing probabilities when listing files @@ -394,6 +443,11 @@ void *do_malloc(unsigned int size) if ((new = malloc(size)) == NULL) { (void) fprintf(stderr, "fortune: out of memory.\n"); + + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } return new; @@ -673,15 +727,6 @@ int add_file(int percent, register char *file, char *dir, fp->path = do_malloc (strlen (path) + 1); strncpy (fp->path, path, strlen (path) + 1); - //FIXME - fp->utf8_charset = FALSE; - testpath = do_malloc(strlen (path) + 4); - sprintf(testpath, "%s.u8", path); -// fprintf(stderr, "State mal: %s\n", testpath); - if(stat(testpath, &statbuf) == 0) - fp->utf8_charset = TRUE; -// fprintf(stderr, "Is utf8?: %i\n", fp->utf8_charset ); - fp->parent = parent; if ((isdir && !add_dir(fp)) || @@ -1135,6 +1180,10 @@ void init_prob(void) { fprintf(stderr, "fortune: probabilities sum to %d%%!\n", percent); + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } else if (percent < 100 && num_noprob == 0) @@ -1142,12 +1191,20 @@ void init_prob(void) fprintf(stderr, "fortune: no place to put residual probability (%d%%)\n", percent); + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } else if (percent == 100 && num_noprob != 0) { fprintf(stderr, "fortune: no probability left to put in residual files\n"); + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } Spec_prob = percent; /* this is for -f when % is specified on cmd line */ @@ -1243,6 +1300,10 @@ void get_tbl(FILEDESC * fp) if ((fd = open(fp->datfile, O_RDONLY)) < 0) { perror(fp->datfile); + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } if (read(fd, &fp->tbl.str_version, sizeof fp->tbl.str_version) != @@ -1250,6 +1311,10 @@ void get_tbl(FILEDESC * fp) { fprintf(stderr, "fortune: %s corrupted\n", fp->path); + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } if (read(fd, &fp->tbl.str_numstr, sizeof fp->tbl.str_numstr) != @@ -1376,6 +1441,10 @@ void open_dat(FILEDESC * fp) if (fp->datfd < 0 && (fp->datfd = open(fp->datfile, O_RDONLY)) < 0) { perror(fp->datfile); + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } } @@ -1480,6 +1549,10 @@ void open_fp(FILEDESC * fp) if (fp->inf == NULL && (fp->inf = fdopen(fp->fd, "r")) == NULL) { perror(fp->path); + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(1); } } @@ -1523,7 +1596,7 @@ void matches_in_list(FILEDESC * list) unsigned char ch; /* -allover */ register FILEDESC *fp; int in_file, nchar; - char *output; + unsigned char buf[BUFSIZ]; for (fp = list; fp != NULL; fp = fp->next) { @@ -1536,7 +1609,9 @@ void matches_in_list(FILEDESC * list) open_fp(fp); sp = Fortbuf; in_file = FALSE; - while (fgets(sp, Fort_len, fp->inf) != NULL) + while (fgets(buf, sizeof buf, fp->inf) != NULL) { + if (fortune_iconv(cd, buf, strlen(buf), sp, Fort_len + 8 - (sp - Fortbuf))) + break; if (!STR_ENDSTRING(sp, fp->tbl)) sp += strlen(sp); else @@ -1544,29 +1619,10 @@ void matches_in_list(FILEDESC * list) *sp = '\0'; nchar = sp - Fortbuf; - if (fp->utf8_charset) - { - output = recode_string (request, Fortbuf); - } else { - output = Fortbuf; - } - /* Should maybe rot13 Fortbuf -allover */ - - if(fp->tbl.str_flags & STR_ROTATED) - { - for (p = 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; - } - } - DPRINTF(1, (stdout, "nchar = %d\n", nchar)); if ( (nchar < SLEN || !Short_only) && (nchar > SLEN || !Long_only) && - RE_EXEC(output) ) + RE_EXEC(Fortbuf) ) { if (!in_file) { @@ -1574,15 +1630,13 @@ void matches_in_list(FILEDESC * list) Found_one = TRUE; in_file = TRUE; } - fputs (output, stdout); + fwrite(Fortbuf, 1, sp - Fortbuf, stdout); printf("%c\n", fp->tbl.str_delim); } - if (fp->utf8_charset) - free (output); - sp = Fortbuf; } + } } } @@ -1607,15 +1661,18 @@ int find_matches(void) void display(FILEDESC * fp) { register char *p, ch; + unsigned char buf[BUFSIZ]; unsigned char line[BUFSIZ]; open_fp(fp); fseek(fp->inf, (long) Seekpts[0], 0); if (Show_filename) printf ("(%s)\n%%\n", fp->name); - for (Fort_len = 0; fgets(line, sizeof line, fp->inf) != NULL && - !STR_ENDSTRING(line, fp->tbl); Fort_len++) + for (Fort_len = 0; fgets(buf, sizeof buf, fp->inf) != NULL && + !STR_ENDSTRING(buf, fp->tbl); Fort_len++) { + if (fortune_iconv(cd, buf, strlen(buf), line, sizeof(line))) + break; if (fp->tbl.str_flags & STR_ROTATED) { for (p = line; (ch = *p); ++p) @@ -1626,20 +1683,9 @@ void display(FILEDESC * fp) *p = 'a' + (ch - 'a' + 13) % 26; } } - if(fp->utf8_charset) { - char *output; - output = recode_string (request, line); - fputs(output, stdout); - free(output); - } - else - fputs(line, stdout); + fputs(line, stdout); } fflush(stdout); - - if(fp->utf8_charset) { - recode_delete_request(request); - } } /* @@ -1673,25 +1719,25 @@ int max(register int i, register int j) int main(int ac, char *av[]) { - char *ctype, *crequest; - getargs(ac, av); + setlocale(LC_ALL, ""); + Codeset = nl_langinfo(CODESET); - outer = recode_new_outer(true); - request = recode_new_request (outer); + if (Codeset && *Codeset) + cd = iconv_open(Codeset, "UTF-8"); - setlocale(LC_ALL,""); - ctype = nl_langinfo(CODESET); - if(strcmp(ctype,"ANSI_X3.4-1968") == 0) - ctype="ISO-8859-1"; - - crequest = malloc(strlen(ctype) + 7 + 1); - sprintf(crequest, "UTF-8..%s", ctype); - recode_scan_request (request, crequest); - free(crequest); + getargs(ac, av); #ifndef NO_REGEX - if (Match) - exit(find_matches() != 0); + if (Match) { + int n; + + n = find_matches() != 0; + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } + exit(n); + } #endif init_prob(); if (Find_files) @@ -1700,6 +1746,11 @@ int main(int ac, char *av[]) if (Equal_probs) calc_equal_probs(); print_list(File_list, 0); + + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(0); } srandom((int) (time((time_t *) NULL) + getpid())); @@ -1717,6 +1768,11 @@ int main(int ac, char *av[]) fortlen(); sleep((unsigned int) max(Fort_len / CPERS, MINW)); } + + if (cd && cd != (iconv_t) -1) { + iconv_close(cd); + cd = NULL; + } exit(0); /* NOTREACHED */ } diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/util/randstr.c b/util/randstr.c index 3300715..52529cd 100644 --- a/util/randstr.c +++ b/util/randstr.c @@ -95,6 +95,11 @@ #include #include #include +/* FIXME(raorn): use ifdef's */ +#include +#include +#include +#include #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif /* MAXPATHLEN */ @@ -107,6 +112,9 @@ FILE *Inf, *Dataf, *Outf; off_t pos, Seekpts[2]; /* seek pointers to fortunes */ +/* FIXME(raorn): use ifdef's */ +iconv_t cd = NULL; +char *Codeset = NULL; void getargs(int ac, char *av[]) { @@ -170,31 +178,94 @@ void get_fort(STRFILE fp) Seekpts[1] = ntohl(Seekpts[1]); } +int fortune_iconv(iconv_t _cd, char *inbuf, int inlen, char *outbuf, int outlen) +{ + char *outptr; + size_t n; + int needed_from; + + if (_cd && _cd == (iconv_t) -1) { + memmove(outbuf, inbuf, inlen); + return 0; + } + + outptr = outbuf; + while (inlen > 0) { + outptr = outbuf; + n = iconv (_cd, (char **) &inbuf, &inlen, &outptr, &outlen); + + if(inlen == 0) break; + + if (n != (size_t) - 1) { + n = iconv (_cd, NULL, NULL, &outptr, &outlen); + + break; + } + + if (errno != E2BIG) { + switch (errno) { + case EILSEQ: + case EINVAL: + needed_from = ((__gconv_t) _cd)->__steps->__min_needed_from; + outptr[0] = '?'; + outptr++; + outlen--; + inbuf += needed_from; + inlen -= needed_from; + break; + default: + return -1; + } + } else { + /* FIXME: no space left in output buffer */ + break; + } + } + outptr[0] = 0; + return 0; +} + void display(FILE * fp, STRFILE table) { register char *p, ch; + unsigned char buf[BUFSIZ]; unsigned char line[BUFSIZ]; int i; + /* FIXME(raorn): use ifdef's */ + if (Codeset && *Codeset) + cd = iconv_open(Codeset, "UTF-8"); + fseek(fp, (long) Seekpts[0], 0); - for (i = 0; fgets(line, sizeof line, fp) != NULL && - !STR_ENDSTRING(line, table); i++) + for (i = 0; fgets(buf, sizeof line, fp) != NULL; i++) { + /* FIXME(raorn): use ifdef's */ + if (fortune_iconv(cd, buf, strlen(buf), line, sizeof(line))) + break; + if (!STR_ENDSTRING(line, table)) + break; if (table.str_flags & STR_ROTATED) for (p = line; (ch = *p); ++p) - if (isupper(ch)) + if (ch >= 'A' && ch <= 'Z') *p = 'A' + (ch - 'A' + 13) % 26; - else if (islower(ch)) + else if (ch >= 'a' && ch <= 'z') *p = 'a' + (ch - 'a' + 13) % 26; fputs(line, stdout); } fflush(stdout); + + if (cd && cd != (iconv_t) -1) + iconv_close(cd); } int main(int ac, char **av) { static STRFILE tbl; /* description table */ + /* FIXME(raorn): use ifdef's */ + setlocale(LC_ALL, ""); + Codeset = nl_langinfo(CODESET); + getargs(ac, av); if ((Inf = fopen(Infile, "r")) == NULL) {