diff -urN calendar-1.25.orig/calendar.h calendar-1.25/calendar.h --- calendar-1.25.orig/calendar.h 2009-03-03 22:37:55.000000000 -0500 +++ calendar-1.25/calendar.h 2009-03-04 00:08:53.000000000 -0500 @@ -31,6 +31,8 @@ #include +#include + extern struct passwd *pw; extern int doall; extern int bodun_always; @@ -70,6 +72,7 @@ int (*getev)(int); }; +void convprint(FILE *, iconv_t, char *); void cal(void); void closecal(FILE *); int getday(char *); diff -urN calendar-1.25.orig/io.c calendar-1.25/io.c --- calendar-1.25.orig/io.c 2009-03-03 22:37:55.000000000 -0500 +++ calendar-1.25/io.c 2009-03-04 00:11:21.000000000 -0500 @@ -61,10 +61,17 @@ #include #include +#include +#include + #include "pathnames.h" #include "calendar.h" +#define ICONV_TRANSLIT "/" "/" "TRANSLIT" +#define ICONV_FROMCODE "UTF-8" +#define ICONV_BUFSIZ (128) + struct iovec header[] = { { "From: ", 6 }, { NULL, 0 }, @@ -76,6 +83,39 @@ { "Auto-Submitted: auto-generated\n\n", 32 }, }; +void +convprint(FILE *fp, iconv_t ic, char *inputbuf) +{ + char *iconv_input; + char *iconv_output; + char outputbuf[ICONV_BUFSIZ]; + size_t inputsz; + size_t outputsz; + size_t iconv_result; + + iconv_input = inputbuf; + inputsz = strlen(inputbuf); + + while (inputsz > 0) + { + iconv_output = outputbuf; + outputsz = sizeof(outputbuf) - 1; + + iconv_result = iconv( + ic, + &iconv_input, + &inputsz, + &iconv_output, + &outputsz + ); + if ((((size_t) -1) == iconv_result) && (E2BIG != errno)) + { + return; + } + outputbuf[sizeof(outputbuf) - outputsz - 1] = '\0'; + (void)fprintf(fp, "%s", outputbuf); + } +} void cal(void) @@ -86,6 +126,42 @@ struct match *m; FILE *fp; + char *langinfo_coding; + char *iconv_coding; + iconv_t ic; + int use_iconv; + + use_iconv = 1; + iconv_coding = NULL; + ic = (iconv_t) -1; + (void)setlocale(LC_ALL, ""); + langinfo_coding = nl_langinfo(CODESET); + if ((NULL == langinfo_coding) || ('\0' == *langinfo_coding)) + { + use_iconv = 0; + } + else + { + iconv_coding = malloc( + strlen(langinfo_coding) + sizeof(ICONV_TRANSLIT) + ); + } + + if (NULL == iconv_coding) + { + use_iconv = 0; + } + else + { + sprintf(iconv_coding, "%s%s", langinfo_coding, ICONV_TRANSLIT); + ic = iconv_open(iconv_coding, ICONV_FROMCODE); + } + + if (((iconv_t) -1) == ic) + { + use_iconv = 0; + } + events = NULL; cur_evt = NULL; if ((fp = opencal()) == NULL) @@ -101,6 +177,14 @@ if (buf[0] == '\0') continue; if (strncmp(buf, "LANG=", 5) == 0) { + if (use_iconv) + { + char *coding_start = strchr(buf, '.'); + if (NULL != coding_start) + { + strcpy(coding_start, ".UTF-8"); + } + } (void) setlocale(LC_ALL, buf + 5); setnnames(); if (!strcmp(buf + 5, "ru_RU.KOI8-R") || @@ -215,8 +299,17 @@ } tmp = events; while (tmp) { + if (use_iconv) + { + convprint(fp, ic, tmp->print_date); + convprint(fp, ic, *(tmp->desc)); + (void)fputc((int) '\n', fp); + } + else + { (void)fprintf(fp, "%s%s\n", tmp->print_date, *(tmp->desc)); - tmp = tmp->next; + } + tmp = tmp->next; } tmp = events; while (tmp) { @@ -226,6 +319,17 @@ tmp = tmp->next; free(events); } + + if (NULL != iconv_coding) + { + free(iconv_coding); + } + + if (((iconv_t) -1) != ic) + { + iconv_close(ic); + } + closecal(fp); }