diff -up calendar-1.26-20110115cvs/calendar.h.coding calendar-1.26-20110115cvs/calendar.h --- calendar-1.26-20110115cvs/calendar.h.coding 2011-01-15 17:27:14.000000000 -1000 +++ calendar-1.26-20110115cvs/calendar.h 2011-01-15 17:27:52.000000000 -1000 @@ -31,6 +31,8 @@ #include <sys/uio.h> +#include <iconv.h> + extern struct passwd *pw; extern int doall; extern int bodun_always; @@ -69,6 +71,7 @@ struct specialev { int (*getev)(int); }; +void convprint(FILE *, iconv_t, char *); void cal(void); void closecal(FILE *); int getday(char *); diff -up calendar-1.26-20110115cvs/io.c.coding calendar-1.26-20110115cvs/io.c --- calendar-1.26-20110115cvs/io.c.coding 2011-01-15 17:27:14.000000000 -1000 +++ calendar-1.26-20110115cvs/io.c 2011-01-15 17:27:52.000000000 -1000 @@ -47,10 +47,17 @@ #include <string.h> #include <unistd.h> +#include <langinfo.h> +#include <iconv.h> + #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 }, @@ -62,6 +69,39 @@ struct iovec header[] = { { "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) @@ -72,6 +112,42 @@ cal(void) 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) @@ -87,6 +163,14 @@ cal(void) 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") || @@ -201,8 +285,17 @@ cal(void) } 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) { @@ -212,6 +305,17 @@ cal(void) tmp = tmp->next; free(events); } + + if (NULL != iconv_coding) + { + free(iconv_coding); + } + + if (((iconv_t) -1) != ic) + { + iconv_close(ic); + } + closecal(fp); }